mirror of
https://github.com/MCV-Software/TWBlue.git
synced 2025-08-26 01:49:22 +00:00
Compare commits
69 Commits
v0.94
...
snapshot10
Author | SHA1 | Date | |
---|---|---|---|
5c75be20d3 | |||
1ccb898f78 | |||
d734a30a18 | |||
3d310c0ee4 | |||
79512af350 | |||
7a2ad3797d | |||
f87312fc53 | |||
682f1e8bd4 | |||
cbc2e978c9 | |||
72fd93eaf6 | |||
8bac4b8ec6 | |||
6c29a4a18f | |||
3ae581a19f | |||
a9378988cb | |||
00f96bb7af | |||
ecd2984a61 | |||
3be69cb6a2 | |||
099bc49761 | |||
ec61f4b431 | |||
b16a6c5ddb | |||
9a94b92018 | |||
fe8a3b1565 | |||
a3d1052193 | |||
fbbd3cf00e | |||
8a6f73fdc2 | |||
c806f17484 | |||
db231e07f8 | |||
eaf13a4453 | |||
d4a73fb3bb | |||
8459135002 | |||
4aef2595b2 | |||
ccdcc7676e | |||
967cc8da71 | |||
071bcf55ef | |||
cf735211c9 | |||
bd56eb953b | |||
940ace664c | |||
![]() |
8619deb6ee | ||
![]() |
9fcc5d36e5 | ||
![]() |
c374cdefe9 | ||
7b925b5909 | |||
013a80a1f2 | |||
ec860aa6fc | |||
12e06eb52d | |||
464fce07b0 | |||
ad484a1f35 | |||
7296d2a939 | |||
cd596a6ad6 | |||
![]() |
ed3b9c9538 | ||
df9d99edcd | |||
![]() |
f5f4074409 | ||
6439eac76c | |||
5c794aaeff | |||
8cdd1b52d1 | |||
6928ac4b99 | |||
ae42a53b41 | |||
be7df1714d | |||
8cf7ca5ef2 | |||
0cfa89b389 | |||
f63ed6d0a7 | |||
00440e9050 | |||
76db14360a | |||
0966739296 | |||
1e27056902 | |||
3b41e18573 | |||
2668e47a6f | |||
b44e30ed28 | |||
bfad5b82f0 | |||
41d4c97067 |
@@ -1,6 +1,8 @@
|
||||
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.
|
||||
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
|
||||
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.
|
||||
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"
|
||||
|
||||
# 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"
|
||||
|
||||
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,6 +2,19 @@
|
||||
|
||||
## changes in this version
|
||||
|
||||
* 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 the Twitter.
|
||||
* Extended Tweets should be displayed properly in list buffers.
|
||||
|
||||
## Changes in version 0.94
|
||||
|
||||
* Added an option in the global settings dialog to disable the Streaming features of TWBlue. TWBlue will remove all Streaming features after August 16, so this option will give people an idea about how it will be. ([#219](https://github.com/manuelcortez/TWBlue/issues/219))
|
||||
* Due to Twitter API changes, Switched authorisation method to Pin-code based authorisation. When you add new accounts to TWBlue, you will be required to paste a code displayed in the Twitter website in order to grant access to TWBlue. ([#216](https://github.com/manuelcortez/TWBlue/issues/216))
|
||||
* In order to comply with latest Twitter changes, TWBlue has switched to the new method used to send and receive direct messages, according to issue [#215.](https://github.com/manuelcortez/twblue/issues/215)
|
||||
|
@@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import markdown
|
||||
import os
|
||||
import shutil
|
||||
from codecs import open as _open
|
||||
import languageHandler
|
||||
languageHandler.setLanguage("en")
|
||||
@@ -38,14 +39,18 @@ def generate_document(language, document_type="documentation"):
|
||||
""" % (language, title, title)
|
||||
first_html_block = first_html_block+ markdown_file
|
||||
first_html_block = first_html_block + "\n</body>\n</html>"
|
||||
if not os.path.exists(language):
|
||||
os.mkdir(language)
|
||||
mdfile = _open("%s/%s" % (language, filename), "w", encoding="utf-8")
|
||||
if not os.path.exists(os.path.join("documentation", language)):
|
||||
os.mkdir(os.path.join("documentation", language))
|
||||
mdfile = _open(os.path.join("documentation", language, filename), "w", encoding="utf-8")
|
||||
mdfile.write(first_html_block)
|
||||
mdfile.close()
|
||||
|
||||
def create_documentation():
|
||||
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:
|
||||
print("Creating documentation for: %s" % (i,))
|
||||
generate_document(i)
|
||||
|
@@ -20,4 +20,6 @@ idna
|
||||
chardet
|
||||
urllib3
|
||||
youtube-dl
|
||||
python-vlc
|
||||
python-vlc
|
||||
pywin32
|
||||
py2exe_py2
|
@@ -2,13 +2,13 @@
|
||||
import datetime
|
||||
|
||||
name = 'TWBlue'
|
||||
snapshot = False
|
||||
snapshot = True
|
||||
if snapshot == False:
|
||||
version = "0.94"
|
||||
update_url = 'https://twblue.es/updates/stable.php'
|
||||
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/stable.json'
|
||||
else:
|
||||
version = "8"
|
||||
version = "9"
|
||||
update_url = 'https://twblue.es/updates/snapshot.php'
|
||||
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/snapshots.json'
|
||||
authors = [u"Manuel Cortéz", u"José Manuel Delicado"]
|
||||
@@ -18,18 +18,4 @@ description = unicode(name+" is an app designed to use Twitter simply and effici
|
||||
translators = [u"Manuel Cortéz (English)", u"Mohammed Al Shara, Hatoun Felemban (Arabic)", u"Francisco Torres (Catalan)", u"Manuel cortéz (Spanish)", u"Sukil Etxenike Arizaleta (Basque)", u"Jani Kinnunen (finnish)", u"Rémy Ruiz (French)", u"Juan Buño (Galician)", u"Steffen Schultz (German)", u"Zvonimir Stanečić (Croatian)", u"Robert Osztolykan (Hungarian)", u"Christian Leo Mameli (Italian)", u"Riku (Japanese)", u"Paweł Masarczyk (Polish)", u"Odenilton Júnior Santos (Portuguese)", u"Florian Ionașcu, Nicușor Untilă (Romanian)", u"Natalia Hedlund, Valeria Kuznetsova (Russian)", u"Aleksandar Đurić (Serbian)", u"Burak Yüksek (Turkish)"]
|
||||
url = u"https://twblue.es"
|
||||
report_bugs_url = "https://github.com/manuelcortez/twblue/issues"
|
||||
supported_languages = []
|
||||
|
||||
def streaming_lives():
|
||||
""" Check if we are in August 16.
|
||||
ToDo: This method should be removed after deadline==True"""
|
||||
# Let's import config here so we will avoid breaking things when setup.py is going to be used.
|
||||
# Check if user has disabled the streaming API things from settings.
|
||||
import config
|
||||
if config.app != None:
|
||||
no_streaming = config.app["app-settings"]["no_streaming"]
|
||||
if no_streaming == True:
|
||||
return False
|
||||
deadline = datetime.date(2018, 8, 16)
|
||||
now = datetime.datetime.now().date()
|
||||
return deadline>now
|
||||
supported_languages = []
|
@@ -18,11 +18,11 @@ import sound
|
||||
import languageHandler
|
||||
import logging
|
||||
import youtube_utils
|
||||
from twitter import compose, utils
|
||||
from sessions.twitter import compose, utils
|
||||
from mysc.thread_utils import call_threaded
|
||||
from twython import TwythonError
|
||||
from pubsub import pub
|
||||
from long_tweets import twishort, tweets
|
||||
from sessions.twitter.long_tweets import twishort, tweets
|
||||
|
||||
log = logging.getLogger("controller.buffers")
|
||||
|
||||
@@ -162,9 +162,11 @@ class bufferController(object):
|
||||
else:
|
||||
text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text, 1)
|
||||
if not hasattr(tweet, "attachments") or len(tweet.attachments) == 0:
|
||||
call_threaded(self.session.api_call, call_name="update_status", status=text, _sound="tweet_send.ogg")
|
||||
else:
|
||||
call_threaded(self.post_with_media, text=text, attachments=tweet.attachments, _sound="tweet_send.ogg")
|
||||
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()
|
||||
|
||||
@@ -172,10 +174,10 @@ class bufferController(object):
|
||||
media_ids = []
|
||||
for i in attachments:
|
||||
photo = open(i["file"], "rb")
|
||||
img = self.session.twitter.twitter.upload_media(media=photo)
|
||||
self.session.twitter.twitter.create_metadata(media_id=img["media_id"], alt_text=dict(text=i["description"]))
|
||||
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.twitter.update_status(status=text, media_ids=media_ids)
|
||||
self.session.twitter.update_status(status=text, media_ids=media_ids)
|
||||
|
||||
def save_positions(self):
|
||||
try:
|
||||
@@ -288,7 +290,7 @@ class baseBufferController(bufferController):
|
||||
if tweet.has_key("message"):
|
||||
message = tweet["message"]
|
||||
try:
|
||||
tweet = self.session.twitter.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")
|
||||
urls = utils.find_urls_in_text(tweet["full_text"])
|
||||
for url in range(0, len(urls)):
|
||||
try: tweet["full_text"] = tweet["full_text"].replace(urls[url], tweet["entities"]["urls"][url]["expanded_url"])
|
||||
@@ -302,7 +304,7 @@ class baseBufferController(bufferController):
|
||||
while l != False:
|
||||
tweetsList.append(tweet)
|
||||
try:
|
||||
tweet = self.session.twitter.twitter.show_status(id=l, include_ext_alt_text=True, tweet_mode="extended")
|
||||
tweet = self.session.twitter.show_status(id=l, include_ext_alt_text=True, tweet_mode="extended")
|
||||
urls = utils.find_urls_in_text(tweet["full_text"])
|
||||
for url in range(0, len(urls)):
|
||||
try: tweet["full_text"] = tweet["full_text"].replace(urls[url], tweet["entities"]["urls"][url]["expanded_url"])
|
||||
@@ -349,6 +351,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)
|
||||
except TwythonError as e:
|
||||
output.speak(e.message, True)
|
||||
if items == None:
|
||||
return
|
||||
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:
|
||||
i = self.session.check_quoted_status(i)
|
||||
@@ -548,7 +552,7 @@ class baseBufferController(bufferController):
|
||||
if len(users) > 0:
|
||||
config.app["app-settings"]["mention_all"] = message.message.mentionAll.GetValue()
|
||||
config.app.write()
|
||||
params = {"_sound": "reply_send.ogg", "in_reply_to_status_id": id,}
|
||||
params = {"_sound": "reply_send.ogg", "in_reply_to_status_id": id, "tweet_mode": "extended"}
|
||||
text = message.message.get_text()
|
||||
if twishort_enabled == False:
|
||||
excluded_ids = message.get_ids()
|
||||
@@ -568,7 +572,10 @@ class baseBufferController(bufferController):
|
||||
else:
|
||||
params["call_name"] = "update_status_with_media"
|
||||
params["media"] = message.file
|
||||
call_threaded(self.session.api_call, **params)
|
||||
|
||||
item = self.session.api_call(**params)
|
||||
if item != None:
|
||||
pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
|
||||
if hasattr(message.message, "destroy"): message.message.destroy()
|
||||
self.session.settings.write()
|
||||
|
||||
@@ -637,13 +644,21 @@ class baseBufferController(bufferController):
|
||||
text = retweet.message.get_text()
|
||||
text = text+" https://twitter.com/{0}/status/{1}".format(tweet["user"]["screen_name"], id)
|
||||
if retweet.image == None:
|
||||
call_threaded(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:
|
||||
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"])
|
||||
else:
|
||||
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()
|
||||
|
||||
def _direct_retweet(self, id):
|
||||
call_threaded(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:
|
||||
# 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"])
|
||||
|
||||
def onFocus(self, *args, **kwargs):
|
||||
tweet = self.get_tweet()
|
||||
@@ -711,10 +726,10 @@ class baseBufferController(bufferController):
|
||||
if answer == widgetUtils.YES:
|
||||
try:
|
||||
if self.name == "direct_messages" or self.name == "sent_direct_messages":
|
||||
self.session.twitter.twitter.destroy_direct_message(id=self.get_right_tweet()["id"])
|
||||
self.session.twitter.destroy_direct_message(id=self.get_right_tweet()["id"])
|
||||
self.session.db[self.name]["items"].pop(index)
|
||||
else:
|
||||
self.session.twitter.twitter.destroy_status(id=self.get_right_tweet()["id"])
|
||||
self.session.twitter.destroy_status(id=self.get_right_tweet()["id"])
|
||||
self.session.db[self.name].pop(index)
|
||||
self.buffer.list.remove_item(index)
|
||||
# if index > 0:
|
||||
@@ -737,7 +752,7 @@ class baseBufferController(bufferController):
|
||||
|
||||
def get_quoted_tweet(self, tweet):
|
||||
# try:
|
||||
quoted_tweet = self.session.twitter.twitter.show_status(id=tweet["id"])
|
||||
quoted_tweet = self.session.twitter.show_status(id=tweet["id"])
|
||||
urls = utils.find_urls_in_text(quoted_tweet["text"])
|
||||
for url in range(0, len(urls)):
|
||||
try: quoted_tweet["text"] = quoted_tweet["text"].replace(urls[url], quoted_tweet["entities"]["urls"][url]["expanded_url"])
|
||||
@@ -748,7 +763,7 @@ class baseBufferController(bufferController):
|
||||
l = tweets.is_long(quoted_tweet)
|
||||
id = tweets.get_id(l)
|
||||
# try:
|
||||
original_tweet = self.session.twitter.twitter.show_status(id=id)
|
||||
original_tweet = self.session.twitter.show_status(id=id)
|
||||
urls = utils.find_urls_in_text(original_tweet["text"])
|
||||
for url in range(0, len(urls)):
|
||||
try: original_tweet["text"] = original_tweet["text"].replace(urls[url], original_tweet["entities"]["urls"][url]["expanded_url"])
|
||||
@@ -763,6 +778,8 @@ class directMessagesController(baseBufferController):
|
||||
except TwythonError as e:
|
||||
output.speak(e.message, True)
|
||||
return
|
||||
if items == None:
|
||||
return
|
||||
sent = []
|
||||
for i in items:
|
||||
if i["message_create"]["sender_id"] == self.session.db["user_id"]:
|
||||
@@ -809,7 +826,9 @@ class directMessagesController(baseBufferController):
|
||||
config.app["app-settings"]["longtweet"] = message.message.long_tweet.GetValue()
|
||||
config.app.write()
|
||||
if message.image == None:
|
||||
call_threaded(self.session.api_call, call_name="update_status", _sound="reply_send.ogg", status=message.message.get_text())
|
||||
item = self.session.api_call(call_name="update_status", _sound="reply_send.ogg", status=message.message.get_text(), tweet_mode="extended")
|
||||
if item != None:
|
||||
pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
|
||||
else:
|
||||
call_threaded(self.session.api_call, call_name="update_status_with_media", _sound="reply_send.ogg", status=message.message.get_text(), media=message.file)
|
||||
if hasattr(message.message, "destroy"): message.message.destroy()
|
||||
@@ -869,7 +888,7 @@ class listBufferController(baseBufferController):
|
||||
def get_user_ids(self):
|
||||
next_cursor = -1
|
||||
while(next_cursor):
|
||||
users = self.session.twitter.twitter.get_list_members(list_id=self.list_id, cursor=next_cursor, include_entities=False, skip_status=True)
|
||||
users = self.session.twitter.get_list_members(list_id=self.list_id, cursor=next_cursor, include_entities=False, skip_status=True)
|
||||
for i in users['users']:
|
||||
if i["id"] not in self.users:
|
||||
self.users.append(i["id"])
|
||||
@@ -1012,7 +1031,9 @@ class peopleBufferController(baseBufferController):
|
||||
config.app["app-settings"]["longtweet"] = message.message.long_tweet.GetValue()
|
||||
config.app.write()
|
||||
if message.image == None:
|
||||
call_threaded(self.session.api_call, call_name="update_status", _sound="reply_send.ogg", status=message.message.get_text())
|
||||
item = self.session.api_call(call_name="update_status", _sound="reply_send.ogg", status=message.message.get_text(), tweet_mode="extended")
|
||||
if item != None:
|
||||
pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
|
||||
else:
|
||||
call_threaded(self.session.api_call, call_name="update_status_with_media", _sound="reply_send.ogg", status=message.message.get_text(), media=message.file)
|
||||
if hasattr(message.message, "destroy"): message.message.destroy()
|
||||
@@ -1039,6 +1060,8 @@ class peopleBufferController(baseBufferController):
|
||||
except TwythonError as e:
|
||||
output.speak(e.message, True)
|
||||
return
|
||||
if items == None:
|
||||
return
|
||||
for i in items:
|
||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||
self.session.db[self.name]["items"].insert(0, i)
|
||||
@@ -1161,6 +1184,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)
|
||||
except TwythonError as e:
|
||||
output.speak(e.message, True)
|
||||
if items == None:
|
||||
return
|
||||
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:
|
||||
i = self.session.check_quoted_status(i)
|
||||
@@ -1223,6 +1248,8 @@ class searchPeopleBufferController(peopleBufferController):
|
||||
except TwythonError as e:
|
||||
output.speak(e.message, True)
|
||||
return
|
||||
if items == None:
|
||||
return
|
||||
for i in items:
|
||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||
self.session.db[self.name]["items"].insert(0, i)
|
||||
@@ -1396,7 +1423,7 @@ class conversationBufferController(searchBufferController):
|
||||
tweet = self.tweet
|
||||
while tweet["in_reply_to_status_id"] != None:
|
||||
try:
|
||||
tweet = self.session.twitter.twitter.show_status(id=tweet["in_reply_to_status_id"], tweet_mode="extended")
|
||||
tweet = self.session.twitter.show_status(id=tweet["in_reply_to_status_id"], tweet_mode="extended")
|
||||
except TwythonError as err:
|
||||
break
|
||||
self.statuses.insert(0, tweet)
|
||||
|
@@ -3,7 +3,7 @@ import widgetUtils
|
||||
import output
|
||||
from wxUI.dialogs import lists
|
||||
from twython import TwythonError
|
||||
from twitter import compose, utils
|
||||
from sessions.twitter import compose, utils
|
||||
from pubsub import pub
|
||||
|
||||
class listsController(object):
|
||||
@@ -29,7 +29,7 @@ class listsController(object):
|
||||
return [compose.compose_list(item) for item in self.session.db["lists"]]
|
||||
|
||||
def get_user_lists(self, user):
|
||||
self.lists = self.session.twitter.twitter.show_lists(reverse=True, screen_name=user)
|
||||
self.lists = self.session.twitter.show_lists(reverse=True, screen_name=user)
|
||||
return [compose.compose_list(item) for item in self.lists]
|
||||
|
||||
def create_list(self, *args, **kwargs):
|
||||
@@ -43,7 +43,7 @@ class listsController(object):
|
||||
else:
|
||||
mode = "private"
|
||||
try:
|
||||
new_list = self.session.twitter.twitter.create_list(name=name, description=description, mode=mode)
|
||||
new_list = self.session.twitter.create_list(name=name, description=description, mode=mode)
|
||||
self.session.db["lists"].append(new_list)
|
||||
self.dialog.lista.insert_item(False, *compose.compose_list(new_list))
|
||||
except TwythonError as e:
|
||||
@@ -63,7 +63,7 @@ class listsController(object):
|
||||
else:
|
||||
mode = "private"
|
||||
try:
|
||||
self.session.twitter.twitter.update_list(list_id=list["id"], name=name, description=description, mode=mode)
|
||||
self.session.twitter.update_list(list_id=list["id"], name=name, description=description, mode=mode)
|
||||
self.session.get_lists()
|
||||
self.dialog.populate_list(self.get_all_lists(), True)
|
||||
except TwythonError as e:
|
||||
@@ -75,7 +75,7 @@ class listsController(object):
|
||||
list = self.session.db["lists"][self.dialog.get_item()]["id"]
|
||||
if lists.remove_list() == widgetUtils.YES:
|
||||
try:
|
||||
self.session.twitter.twitter.delete_list(list_id=list)
|
||||
self.session.twitter.delete_list(list_id=list)
|
||||
self.session.db["lists"].pop(self.dialog.get_item())
|
||||
self.dialog.lista.remove_item(self.dialog.get_item())
|
||||
except TwythonError as e:
|
||||
@@ -90,7 +90,7 @@ class listsController(object):
|
||||
if self.dialog.lista.get_count() == 0: return
|
||||
list_id = self.lists[self.dialog.get_item()]["id"]
|
||||
try:
|
||||
list = self.session.twitter.twitter.subscribe_to_list(list_id=list_id)
|
||||
list = self.session.twitter.subscribe_to_list(list_id=list_id)
|
||||
item = utils.find_item(list["id"], self.session.db["lists"])
|
||||
self.session.db["lists"].append(list)
|
||||
except TwythonError as e:
|
||||
@@ -100,7 +100,7 @@ class listsController(object):
|
||||
if self.dialog.lista.get_count() == 0: return
|
||||
list_id = self.lists[self.dialog.get_item()]["id"]
|
||||
try:
|
||||
list = self.session.twitter.twitter.unsubscribe_from_list(list_id=list_id)
|
||||
list = self.session.twitter.unsubscribe_from_list(list_id=list_id)
|
||||
self.session.db["lists"].remove(list)
|
||||
except TwythonError as e:
|
||||
output.speak("error %s: %s" % (e.status_code, e.msg))
|
||||
|
@@ -2,6 +2,7 @@
|
||||
import platform
|
||||
system = platform.system()
|
||||
import application
|
||||
import requests
|
||||
import youtube_utils
|
||||
if system == "Windows":
|
||||
from update import updater
|
||||
@@ -18,12 +19,13 @@ if system == "Windows":
|
||||
# from issueReporter import issueReporter
|
||||
elif system == "Linux":
|
||||
from gtkUI import (view, commonMessageDialogs)
|
||||
from twitter import utils, compose
|
||||
from sessions.twitter import utils, compose
|
||||
from sessionmanager import manager, sessionManager
|
||||
|
||||
import buffersController
|
||||
import messages
|
||||
from sessionmanager import session as session_
|
||||
import sessions
|
||||
from sessions.twitter import session as session_
|
||||
from pubsub import pub
|
||||
import sound
|
||||
import output
|
||||
@@ -39,6 +41,7 @@ import logging
|
||||
import webbrowser
|
||||
from mysc import localization
|
||||
import os
|
||||
import languageHandler
|
||||
|
||||
log = logging.getLogger("mainController")
|
||||
|
||||
@@ -108,27 +111,6 @@ class Controller(object):
|
||||
[results.append(self.search_buffer(i.name, i.account)) for i in buffers if i.account == account and (i.type != "account")]
|
||||
return results
|
||||
|
||||
def bind_stream_events(self):
|
||||
""" Binds all the streaming events with their functions."""
|
||||
log.debug("Binding events for the Twitter stream API...")
|
||||
pub.subscribe(self.manage_home_timelines, "item-in-home")
|
||||
pub.subscribe(self.manage_mentions, "mention")
|
||||
pub.subscribe(self.manage_direct_messages, "direct-message")
|
||||
pub.subscribe(self.manage_sent_tweets, "sent-tweet")
|
||||
pub.subscribe(self.manage_events, "event")
|
||||
pub.subscribe(self.manage_followers, "follower")
|
||||
pub.subscribe(self.manage_friend, "friend")
|
||||
pub.subscribe(self.manage_unfollowing, "unfollowing")
|
||||
pub.subscribe(self.manage_favourite, "favourite")
|
||||
pub.subscribe(self.manage_unfavourite, "unfavourite")
|
||||
pub.subscribe(self.manage_blocked_user, "blocked-user")
|
||||
pub.subscribe(self.manage_unblocked_user, "unblocked-user")
|
||||
pub.subscribe(self.manage_item_in_timeline, "item-in-timeline")
|
||||
pub.subscribe(self.manage_item_in_list, "item-in-list")
|
||||
pub.subscribe(self.on_tweet_deleted, "tweet-deleted")
|
||||
pub.subscribe(self.manage_stream_errors, "stream-error")
|
||||
# pub.subscribe(self.restart_streams, "restart-streams")
|
||||
|
||||
def bind_other_events(self):
|
||||
""" Binds the local application events with their functions."""
|
||||
log.debug("Binding other application events...")
|
||||
@@ -142,6 +124,13 @@ class Controller(object):
|
||||
pub.subscribe(self.search_topic, "search")
|
||||
pub.subscribe(self.update_sent_dms, "sent-dms-updated")
|
||||
pub.subscribe(self.more_dms, "more-sent-dms")
|
||||
pub.subscribe(self.manage_sent_tweets, "sent-tweet")
|
||||
pub.subscribe(self.manage_friend, "friend")
|
||||
pub.subscribe(self.manage_unfollowing, "unfollowing")
|
||||
pub.subscribe(self.manage_favourite, "favourite")
|
||||
pub.subscribe(self.manage_unfavourite, "unfavourite")
|
||||
pub.subscribe(self.manage_blocked_user, "blocked-user")
|
||||
pub.subscribe(self.manage_unblocked_user, "unblocked-user")
|
||||
if system == "Windows":
|
||||
pub.subscribe(self.invisible_shorcuts_changed, "invisible-shorcuts-changed")
|
||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.show_hide, menuitem=self.view.show_hide)
|
||||
@@ -165,7 +154,7 @@ class Controller(object):
|
||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.post_reply, self.view.reply)
|
||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.post_retweet, self.view.retweet)
|
||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.add_to_favourites, self.view.fav)
|
||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.remove_from_favourites, self.view.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.reverse_geocode, menuitem=self.view.view_coordinates)
|
||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.delete, self.view.delete)
|
||||
@@ -179,6 +168,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.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.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.update_profile, menuitem=self.view.updateProfile)
|
||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.user_details, menuitem=self.view.details)
|
||||
@@ -234,8 +224,6 @@ class Controller(object):
|
||||
# This saves the current account (important in invisible mode)
|
||||
self.current_account = ""
|
||||
self.view.prepare()
|
||||
if application.streaming_lives():
|
||||
self.bind_stream_events()
|
||||
self.bind_other_events()
|
||||
if system == "Windows":
|
||||
self.set_systray_icon()
|
||||
@@ -255,12 +243,12 @@ class Controller(object):
|
||||
def do_work(self):
|
||||
""" Creates the buffer objects for all accounts. This does not starts the buffer streams, only creates the objects."""
|
||||
log.debug("Creating buffers for all sessions...")
|
||||
for i in session_.sessions:
|
||||
for i in sessions.sessions:
|
||||
log.debug("Working on session %s" % (i,))
|
||||
if session_.sessions[i].is_logged == False:
|
||||
self.create_ignored_session_buffer(session_.sessions[i])
|
||||
if sessions.sessions[i].is_logged == False:
|
||||
self.create_ignored_session_buffer(sessions.sessions[i])
|
||||
continue
|
||||
self.create_buffers(session_.sessions[i])
|
||||
self.create_buffers(sessions.sessions[i])
|
||||
|
||||
# Connection checker executed each minute.
|
||||
self.checker_function = RepeatingTimer(60, self.check_connection)
|
||||
@@ -273,12 +261,12 @@ class Controller(object):
|
||||
|
||||
def start(self):
|
||||
""" Starts all buffer objects. Loads their items."""
|
||||
for i in session_.sessions:
|
||||
if session_.sessions[i].is_logged == False: continue
|
||||
self.start_buffers(session_.sessions[i])
|
||||
self.set_buffer_positions(session_.sessions[i])
|
||||
for i in sessions.sessions:
|
||||
if sessions.sessions[i].is_logged == False: continue
|
||||
self.start_buffers(sessions.sessions[i])
|
||||
self.set_buffer_positions(sessions.sessions[i])
|
||||
if config.app["app-settings"]["play_ready_sound"] == True:
|
||||
session_.sessions[session_.sessions.keys()[0]].sound.play("ready.ogg")
|
||||
sessions.sessions[sessions.sessions.keys()[0]].sound.play("ready.ogg")
|
||||
if config.app["app-settings"]["speak_ready_msg"] == True:
|
||||
output.speak(_(u"Ready"))
|
||||
self.started = True
|
||||
@@ -292,8 +280,8 @@ class Controller(object):
|
||||
self.view.add_buffer(account.buffer , name=session.settings["twitter"]["user_name"])
|
||||
|
||||
def login_account(self, session_id):
|
||||
for i in session_.sessions:
|
||||
if session_.sessions[i].session_id == session_id: session = session_.sessions[i]
|
||||
for i in sessions.sessions:
|
||||
if sessions.sessions[i].session_id == session_id: session = sessions.sessions[i]
|
||||
session.login()
|
||||
session.db = dict()
|
||||
self.create_buffers(session, False)
|
||||
@@ -325,7 +313,7 @@ class Controller(object):
|
||||
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")
|
||||
self.buffers.append(sent_dm)
|
||||
self.view.insert_buffer(sent_dm.buffer, name=_(u"Sent Direct messages"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
|
||||
self.view.insert_buffer(sent_dm.buffer, name=_(u"Sent direct messages"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
|
||||
elif i == 'sent_tweets':
|
||||
sent_tweets = buffersController.baseBufferController(self.view.nb, "get_user_timeline", "sent_tweets", session, session.db["user_name"], screen_name=session.db["user_name"], tweet_mode="extended")
|
||||
self.buffers.append(sent_tweets)
|
||||
@@ -350,10 +338,6 @@ class Controller(object):
|
||||
muted = buffersController.peopleBufferController(self.view.nb, "list_mutes", "muted", session, session.db["user_name"])
|
||||
self.buffers.append(muted)
|
||||
self.view.insert_buffer(muted.buffer, name=_(u"Muted users"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
|
||||
elif i == 'events' and application.streaming_lives():
|
||||
events = buffersController.eventsBufferController(self.view.nb, "events", session, session.db["user_name"], bufferType="dmPanel", screen_name=session.db["user_name"])
|
||||
self.buffers.append(events)
|
||||
self.view.insert_buffer(events.buffer, name=_(u"Events"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
|
||||
timelines = buffersController.emptyPanel(self.view.nb, "timelines", session.db["user_name"])
|
||||
self.buffers.append(timelines)
|
||||
self.view.insert_buffer(timelines.buffer , name=_(u"Timelines"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
|
||||
@@ -411,8 +395,8 @@ class Controller(object):
|
||||
i.buffer.list.select_item(session.db[str(i.name+"_pos")])
|
||||
|
||||
def logout_account(self, session_id):
|
||||
for i in session_.sessions:
|
||||
if session_.sessions[i].session_id == session_id: session = session_.sessions[i]
|
||||
for i in sessions.sessions:
|
||||
if sessions.sessions[i].session_id == session_id: session = sessions.sessions[i]
|
||||
user = session.db["user_name"]
|
||||
delete_buffers = []
|
||||
for i in self.buffers:
|
||||
@@ -572,13 +556,12 @@ class Controller(object):
|
||||
dlg.populate_list([compose.compose_list(item) for item in buff.session.db["lists"]])
|
||||
if dlg.get_response() == widgetUtils.OK:
|
||||
try:
|
||||
list = buff.session.twitter.twitter.add_list_member(list_id=buff.session.db["lists"][dlg.get_item()]["id"], screen_name=user)
|
||||
list = buff.session.twitter.add_list_member(list_id=buff.session.db["lists"][dlg.get_item()]["id"], screen_name=user)
|
||||
older_list = utils.find_item(buff.session.db["lists"][dlg.get_item()]["id"], buff.session.db["lists"])
|
||||
listBuffer = self.search_buffer("%s-list" % (buff.session.db["lists"][dlg.get_item()]["name"].lower()), buff.session.db["user_name"])
|
||||
if listBuffer != None: listBuffer.get_user_ids()
|
||||
buff.session.db["lists"].pop(older_list)
|
||||
buff.session.db["lists"].append(list)
|
||||
if listBuffer != None: pub.sendMessage("restart-streams", streams=["timelinesStream"], session=buff.session)
|
||||
except TwythonError as e:
|
||||
output.speak("error %s: %s" % (e.error_code, e.msg))
|
||||
|
||||
@@ -601,13 +584,12 @@ class Controller(object):
|
||||
dlg.populate_list([compose.compose_list(item) for item in buff.session.db["lists"]])
|
||||
if dlg.get_response() == widgetUtils.OK:
|
||||
try:
|
||||
list = buff.session.twitter.twitter.delete_list_member(list_id=buff.session.db["lists"][dlg.get_item()]["id"], screen_name=user)
|
||||
list = buff.session.twitter.delete_list_member(list_id=buff.session.db["lists"][dlg.get_item()]["id"], screen_name=user)
|
||||
older_list = utils.find_item(buff.session.db["lists"][dlg.get_item()]["id"], buff.session.db["lists"])
|
||||
listBuffer = self.search_buffer("%s-list" % (buff.session.db["lists"][dlg.get_item()]["name"].lower()), buff.session.db["user_name"])
|
||||
if listBuffer != None: listBuffer.get_user_ids()
|
||||
buff.session.db["lists"].pop(older_list)
|
||||
buff.session.db["lists"].append(list)
|
||||
if listBuffer != None: pub.sendMessage("restart-streams", streams=["timelinesStream"], session=buff.session)
|
||||
except TwythonError as e:
|
||||
output.speak("error %s: %s" % (e.error_code, e.msg))
|
||||
|
||||
@@ -664,14 +646,12 @@ class Controller(object):
|
||||
for i in self.buffers: i.save_positions()
|
||||
log.debug("Exiting...")
|
||||
log.debug("Saving global configuration...")
|
||||
for item in session_.sessions:
|
||||
if session_.sessions[item].logged == False: continue
|
||||
log.debug("Disconnecting streams for %s session" % (session_.sessions[item].session_id,))
|
||||
if hasattr(session_.sessions[item], "main_stream"): session_.sessions[item].main_stream.disconnect()
|
||||
if hasattr(session_.sessions[item], "timelinesStream"): session_.sessions[item].timelinesStream.disconnect()
|
||||
session_.sessions[item].sound.cleaner.cancel()
|
||||
log.debug("Shelving database for " + session_.sessions[item].session_id)
|
||||
session_.sessions[item].shelve()
|
||||
for item in sessions.sessions:
|
||||
if sessions.sessions[item].logged == False: continue
|
||||
log.debug("Disconnecting streams for %s session" % (sessions.sessions[item].session_id,))
|
||||
sessions.sessions[item].sound.cleaner.cancel()
|
||||
log.debug("Shelving database for " + sessions.sessions[item].session_id)
|
||||
sessions.sessions[item].shelve()
|
||||
if system == "Windows":
|
||||
self.systrayIcon.RemoveIcon()
|
||||
widgetUtils.exit_application()
|
||||
@@ -804,7 +784,7 @@ class Controller(object):
|
||||
return
|
||||
else:
|
||||
id = buffer.get_tweet()["id"]
|
||||
tweet = buffer.session.twitter.twitter.show_status(id=id, include_ext_alt_text=True, tweet_mode="extended")
|
||||
tweet = buffer.session.twitter.show_status(id=id, include_ext_alt_text=True, tweet_mode="extended")
|
||||
if tweet["favorited"] == False:
|
||||
call_threaded(buffer.session.api_call, call_name="create_favorite", _sound="favourite.ogg", id=id)
|
||||
else:
|
||||
@@ -839,7 +819,7 @@ class Controller(object):
|
||||
users = utils.get_all_users(tweet, buff.session.db)
|
||||
dlg = dialogs.userSelection.selectUserDialog(users=users, default=default)
|
||||
if dlg.get_response() == widgetUtils.OK:
|
||||
usr = utils.if_user_exists(buff.session.twitter.twitter, dlg.get_user())
|
||||
usr = utils.if_user_exists(buff.session.twitter, dlg.get_user())
|
||||
if usr != None:
|
||||
if usr == dlg.get_user():
|
||||
commonMessageDialogs.suspended_user()
|
||||
@@ -848,9 +828,6 @@ class Controller(object):
|
||||
if usr["following"] == False:
|
||||
commonMessageDialogs.no_following()
|
||||
return
|
||||
if application.streaming_lives():
|
||||
answer = commonMessageDialogs.protected_user()
|
||||
if answer == widgetUtils.NO: return
|
||||
tl_type = dlg.get_action()
|
||||
if tl_type == "tweets":
|
||||
if usr["statuses_count"] == 0:
|
||||
@@ -870,7 +847,6 @@ class Controller(object):
|
||||
self.view.insert_buffer(tl.buffer, name=_(u"Timeline for {}").format(dlg.get_user()), pos=pos)
|
||||
buff.session.settings["other_buffers"]["timelines"].append(usr["id_str"])
|
||||
pub.sendMessage("buffer-title-changed", buffer=tl)
|
||||
pub.sendMessage("restart-streams", streams=["timelinesStream"], session=buff.session)
|
||||
buff.session.sound.play("create_timeline.ogg")
|
||||
elif tl_type == "favourites":
|
||||
if usr["favourites_count"] == 0:
|
||||
@@ -941,7 +917,6 @@ class Controller(object):
|
||||
search.tweet = buffer.get_right_tweet()
|
||||
search.start_stream(start=True)
|
||||
pos=self.view.search("searches", buffer.session.db["user_name"])
|
||||
# self.buffers.append(search)
|
||||
self.insert_buffer(search, pos)
|
||||
self.view.insert_buffer(search.buffer, name=_(u"Conversation with {0}").format(user), pos=pos)
|
||||
|
||||
@@ -980,7 +955,7 @@ class Controller(object):
|
||||
if tweet["coordinates"] != None:
|
||||
x = tweet["coordinates"]["coordinates"][0]
|
||||
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"))
|
||||
else: self.view.show_address(address[0].__str__().decode("utf-8"))
|
||||
else:
|
||||
@@ -1000,7 +975,7 @@ class Controller(object):
|
||||
if tweet["coordinates"] != None:
|
||||
x = tweet["coordinates"]["coordinates"][0]
|
||||
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__())
|
||||
else:
|
||||
output.speak(_(u"There are no coordinates in this tweet"))
|
||||
@@ -1270,32 +1245,6 @@ class Controller(object):
|
||||
if message != None:
|
||||
output.speak(message, speech=session.settings["reporting"]["speech_reporting"], braille=session.settings["reporting"]["braille_reporting"])
|
||||
|
||||
def manage_home_timelines(self, data, user):
|
||||
buffer = self.search_buffer("home_timeline", user)
|
||||
if buffer == None: return
|
||||
play_sound = "tweet_received.ogg"
|
||||
if "home_timeline" not in buffer.session.settings["other_buffers"]["muted_buffers"]:
|
||||
self.notify(buffer.session, play_sound=play_sound)
|
||||
buffer.add_new_item(data)
|
||||
|
||||
def manage_mentions(self, data, user):
|
||||
buffer = self.search_buffer("mentions", user)
|
||||
if buffer == None: return
|
||||
play_sound = "mention_received.ogg"
|
||||
message = _(u"One mention from %s ") % (data["user"]["name"])
|
||||
if "mentions" not in buffer.session.settings["other_buffers"]["muted_buffers"]:
|
||||
self.notify(buffer.session, play_sound=play_sound, message=message)
|
||||
buffer.add_new_item(data)
|
||||
|
||||
def manage_direct_messages(self, data, user):
|
||||
buffer = self.search_buffer("direct_messages", user)
|
||||
if buffer == None: return
|
||||
play_sound = "dm_received.ogg"
|
||||
message = _(u"New direct message")
|
||||
if "direct_messages" not in buffer.session.settings["other_buffers"]["muted_buffers"]:
|
||||
self.notify(buffer.session, play_sound=play_sound, message=message)
|
||||
buffer.add_new_item(data)
|
||||
|
||||
def manage_sent_dm(self, data, user):
|
||||
buffer = self.search_buffer("sent_direct_messages", user)
|
||||
if buffer == None: return
|
||||
@@ -1307,38 +1256,23 @@ class Controller(object):
|
||||
def manage_sent_tweets(self, data, user):
|
||||
buffer = self.search_buffer("sent_tweets", user)
|
||||
if buffer == None: return
|
||||
play_sound = "tweet_send.ogg"
|
||||
if "sent_tweets" not in buffer.session.settings["other_buffers"]["muted_buffers"]:
|
||||
self.notify(buffer.session, play_sound=play_sound)
|
||||
buffer.add_new_item(data)
|
||||
|
||||
def manage_events(self, data, user):
|
||||
buffer = self.search_buffer("events", user)
|
||||
if buffer == None: return
|
||||
play_sound = "new_event.ogg"
|
||||
if "events" not in buffer.session.settings["other_buffers"]["muted_buffers"]:
|
||||
self.notify(buffer.session, play_sound=play_sound)
|
||||
buffer.add_new_item(data)
|
||||
|
||||
def manage_followers(self, data, user):
|
||||
buffer = self.search_buffer("followers", user)
|
||||
if buffer == None: return
|
||||
play_sound = "update_followers.ogg"
|
||||
if "followers" not in buffer.session.settings["other_buffers"]["muted_buffers"]:
|
||||
self.notify(buffer.session, play_sound=play_sound)
|
||||
# if "sent_tweets" not in buffer.session.settings["other_buffers"]["muted_buffers"]:
|
||||
# self.notify(buffer.session, play_sound=play_sound)
|
||||
if buffer.session.settings["general"]["reverse_timelines"] == False:
|
||||
buffer.session.db[buffer.name].append(data)
|
||||
else:
|
||||
buffer.session.db[buffer.name].insert(0, data)
|
||||
buffer.add_new_item(data)
|
||||
|
||||
def manage_friend(self, data, user):
|
||||
buffer = self.search_buffer("friends", user)
|
||||
if buffer == None: return
|
||||
buffer.add_new_item(data)
|
||||
pub.sendMessage("restart-streams", streams=["main_stream"], session=buffer.session)
|
||||
|
||||
def manage_unfollowing(self, item, user):
|
||||
buffer = self.search_buffer("friends", user)
|
||||
if buffer == None: return
|
||||
buffer.remove_item(item)
|
||||
pub.sendMessage("restart-streams", streams=["main_stream"], session=buffer.session)
|
||||
|
||||
def manage_favourite(self, data, user):
|
||||
buffer = self.search_buffer("favourites", user)
|
||||
@@ -1357,29 +1291,11 @@ class Controller(object):
|
||||
buffer = self.search_buffer("blocked", user)
|
||||
if buffer == None: return
|
||||
buffer.add_new_item(data)
|
||||
pub.sendMessage("restart-streams", streams=["main_stream"], session=buffer.session)
|
||||
|
||||
def manage_unblocked_user(self, item, user):
|
||||
buffer = self.search_buffer("blocked", user)
|
||||
if buffer == None: return
|
||||
buffer.remove_item(item)
|
||||
pub.sendMessage("restart-streams", streams=["main_stream"], session=buffer.session)
|
||||
|
||||
def manage_item_in_timeline(self, data, user, who):
|
||||
buffer = self.search_buffer("%s-timeline" % (who,), user)
|
||||
if buffer == None: return
|
||||
play_sound = "tweet_timeline.ogg"
|
||||
if "%s-timeline" % (who,) not in buffer.session.settings["other_buffers"]["muted_buffers"] and buffer.session.settings["sound"]["session_mute"] == False:
|
||||
self.notify(buffer.session, play_sound=play_sound, message=_(u"One tweet from %s") % (data["user"]["name"]))
|
||||
buffer.add_new_item(data)
|
||||
|
||||
def manage_item_in_list(self, data, user, where):
|
||||
buffer = self.search_buffer("%s" % (where,), user)
|
||||
if buffer == None: return
|
||||
play_sound = "list_tweet.ogg"
|
||||
if "%s" % (where,) not in buffer.session.settings["other_buffers"]["muted_buffers"] and buffer.session.settings["sound"]["session_mute"] == False:
|
||||
self.notify(buffer.session, play_sound=play_sound, message=_(u"One tweet from %s") % (data["user"]["name"]))
|
||||
buffer.add_new_item(data)
|
||||
|
||||
def start_buffers(self, session):
|
||||
log.debug("starting buffers... Session %s" % (session.session_id,))
|
||||
@@ -1406,37 +1322,18 @@ class Controller(object):
|
||||
continue
|
||||
if change_title:
|
||||
pub.sendMessage("buffer-title-changed", buffer=i)
|
||||
if application.streaming_lives():
|
||||
log.debug("Starting the streaming endpoint")
|
||||
session.start_streaming()
|
||||
|
||||
def set_positions(self):
|
||||
for i in session_.sessions:
|
||||
for i in sessions.sessions:
|
||||
self.set_buffer_positions(i)
|
||||
|
||||
def manage_stream_errors(self, session):
|
||||
log.error(" Restarting %s session streams. It will be destroyed" % (session,))
|
||||
s = session_.sessions[session]
|
||||
try:
|
||||
if hasattr(s, "main_stream"):
|
||||
s.main_stream.disconnect()
|
||||
log.error("main stream disconnected")
|
||||
del s.main_stream
|
||||
if hasattr(s, "timelinesStream"):
|
||||
s.timelinesStream.disconnect()
|
||||
del s.timelinesStream
|
||||
except AttributeError:
|
||||
pass
|
||||
s.counter = 0
|
||||
# s.listen_stream_error()
|
||||
|
||||
def check_connection(self):
|
||||
if self.started == False:
|
||||
return
|
||||
for i in session_.sessions:
|
||||
for i in sessions.sessions:
|
||||
try:
|
||||
if session_.sessions[i].is_logged == False: continue
|
||||
session_.sessions[i].check_connection()
|
||||
if sessions.sessions[i].is_logged == False: continue
|
||||
sessions.sessions[i].check_connection()
|
||||
except TwythonError: # We shouldn't allow this function to die.
|
||||
pass
|
||||
|
||||
@@ -1444,7 +1341,7 @@ class Controller(object):
|
||||
buff = self.search_buffer("home_timeline", account)
|
||||
if create == True:
|
||||
if buffer == "favourites":
|
||||
favourites = buffersController.baseBufferController(self.view.nb, "get_favorites", "favourites", buff.session, buff.session.db["user_name"])
|
||||
favourites = buffersController.baseBufferController(self.view.nb, "get_favorites", "favourites", buff.session, buff.session.db["user_name"], tweet_mode="extended")
|
||||
self.buffers.append(favourites)
|
||||
self.view.insert_buffer(favourites.buffer, name=_(u"Likes"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"]))
|
||||
favourites.start_stream(play_sound=False)
|
||||
@@ -1478,7 +1375,7 @@ class Controller(object):
|
||||
if create in buff.session.settings["other_buffers"]["lists"]:
|
||||
output.speak(_(u"This list is already opened"), True)
|
||||
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 = 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"]), tweet_mode="extended")
|
||||
buff.session.lists.append(tl)
|
||||
pos=self.view.search("lists", buff.session.db["user_name"])
|
||||
self.insert_buffer(tl, pos)
|
||||
@@ -1486,13 +1383,6 @@ class Controller(object):
|
||||
tl.start_stream(play_sound=False)
|
||||
buff.session.settings["other_buffers"]["lists"].append(create)
|
||||
buff.session.settings.write()
|
||||
pub.sendMessage("restart-streams", streams=["timelinesStream"], session=buff.session)
|
||||
|
||||
def restart_streams(self, streams=[], session=None):
|
||||
for i in streams:
|
||||
log.debug("Restarting the %s stream" % (i,))
|
||||
session.remove_stream(i)
|
||||
session.check_connection()
|
||||
|
||||
def invisible_shorcuts_changed(self, registered):
|
||||
if registered == True:
|
||||
@@ -1505,22 +1395,51 @@ class Controller(object):
|
||||
def about(self, *args, **kwargs):
|
||||
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):
|
||||
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):
|
||||
sm = sessionManager.sessionManagerController(started=True)
|
||||
sm.fill_list()
|
||||
sm.show()
|
||||
for i in sm.new_sessions:
|
||||
self.create_buffers(session_.sessions[i])
|
||||
call_threaded(self.start_buffers, session_.sessions[i])
|
||||
self.create_buffers(sessions.sessions[i])
|
||||
call_threaded(self.start_buffers, sessions.sessions[i])
|
||||
for i in sm.removed_sessions:
|
||||
if session_.sessions[i].logged == True:
|
||||
self.logout_account(session_.sessions[i].session_id)
|
||||
self.destroy_buffer(session_.sessions[i].settings["twitter"]["user_name"], session_.sessions[i].settings["twitter"]["user_name"])
|
||||
self.accounts.remove(session_.sessions[i].settings["twitter"]["user_name"])
|
||||
session_.sessions.pop(i)
|
||||
if sessions.sessions[i].logged == True:
|
||||
self.logout_account(sessions.sessions[i].session_id)
|
||||
self.destroy_buffer(sessions.sessions[i].settings["twitter"]["user_name"], sessions.sessions[i].settings["twitter"]["user_name"])
|
||||
self.accounts.remove(sessions.sessions[i].settings["twitter"]["user_name"])
|
||||
sessions.sessions.pop(i)
|
||||
|
||||
def update_profile(self, *args, **kwargs):
|
||||
r = user.profileController(self.get_best_buffer().session)
|
||||
@@ -1618,12 +1537,6 @@ class Controller(object):
|
||||
if n != None:
|
||||
output.speak(_(u"{0} items retrieved").format(n,))
|
||||
|
||||
def on_tweet_deleted(self, data):
|
||||
id = data["delete"]["status"]["id"]
|
||||
for i in self.buffers:
|
||||
if hasattr(i, "remove_tweet") and hasattr(i, "name"):
|
||||
i.remove_tweet(id)
|
||||
|
||||
def buffer_title_changed(self, buffer):
|
||||
if "-timeline" in buffer.name:
|
||||
title = _(u"Timeline for {}").format(buffer.username,)
|
||||
@@ -1678,5 +1591,5 @@ class Controller(object):
|
||||
sent_dms.put_more_items(data)
|
||||
|
||||
def save_data_in_db(self):
|
||||
for i in session_.sessions:
|
||||
session_.sessions[i].shelve()
|
||||
for i in sessions.sessions:
|
||||
sessions.sessions[i].shelve()
|
||||
|
@@ -17,7 +17,7 @@ if system == "Windows":
|
||||
from extra.AudioUploader import audioUploader
|
||||
elif system == "Linux":
|
||||
from gtkUI.dialogs import message
|
||||
from twitter import utils
|
||||
from sessions.twitter import utils
|
||||
|
||||
class basicTweet(object):
|
||||
""" This class handles the tweet main features. Other classes should derive from this class."""
|
||||
|
@@ -138,8 +138,6 @@ class accountSettingsController(globalSettingsController):
|
||||
widgetUtils.connect_event(self.dialog.general.au, widgetUtils.BUTTON_PRESSED, self.manage_autocomplete)
|
||||
self.dialog.set_value("general", "relative_time", self.config["general"]["relative_times"])
|
||||
self.dialog.set_value("general", "show_screen_names", self.config["general"]["show_screen_names"])
|
||||
if application.streaming_lives():
|
||||
self.dialog.set_value("general", "apiCalls", self.config["general"]["max_api_calls"])
|
||||
self.dialog.set_value("general", "itemsPerApiCall", self.config["general"]["max_tweets_per_call"])
|
||||
self.dialog.set_value("general", "reverse_timelines", self.config["general"]["reverse_timelines"])
|
||||
rt = self.config["general"]["retweet_mode"]
|
||||
@@ -191,8 +189,6 @@ class accountSettingsController(globalSettingsController):
|
||||
self.needs_restart = True
|
||||
self.config["general"]["relative_times"] = self.dialog.get_value("general", "relative_time")
|
||||
self.config["general"]["show_screen_names"] = self.dialog.get_value("general", "show_screen_names")
|
||||
if application.streaming_lives():
|
||||
self.config["general"]["max_api_calls"] = self.dialog.get_value("general", "apiCalls")
|
||||
self.config["general"]["max_tweets_per_call"] = self.dialog.get_value("general", "itemsPerApiCall")
|
||||
if self.config["general"]["persist_size"] != self.dialog.get_value("general", "persist_size"):
|
||||
if self.dialog.get_value("general", "persist_size") == '':
|
||||
@@ -293,8 +289,6 @@ class accountSettingsController(globalSettingsController):
|
||||
all_buffers['friends']=_(u"Friends")
|
||||
all_buffers['blocks']=_(u"Blocked users")
|
||||
all_buffers['muted']=_(u"Muted users")
|
||||
if application.streaming_lives():
|
||||
all_buffers['events']=_(u"Events")
|
||||
list_buffers = []
|
||||
hidden_buffers=[]
|
||||
for i in all_buffers.keys():
|
||||
|
@@ -8,7 +8,7 @@ class trendingTopicsController(object):
|
||||
self.countries = {}
|
||||
self.cities = {}
|
||||
self.dialog = trends.trendingTopicsDialog()
|
||||
self.information = session.twitter.twitter.get_available_trends()
|
||||
self.information = session.twitter.get_available_trends()
|
||||
self.split_information()
|
||||
widgetUtils.connect_event(self.dialog.country, widgetUtils.RADIOBUTTON, self.get_places)
|
||||
widgetUtils.connect_event(self.dialog.city, widgetUtils.RADIOBUTTON, self.get_places)
|
||||
|
@@ -41,9 +41,9 @@ class profileController(object):
|
||||
self.do_update()
|
||||
|
||||
def get_data(self, screen_name):
|
||||
self.data = self.session.twitter.twitter.show_user(screen_name=screen_name)
|
||||
self.data = self.session.twitter.show_user(screen_name=screen_name)
|
||||
if screen_name != self.session.db["user_name"]:
|
||||
self.friendship_status = self.session.twitter.twitter.show_friendship(source_screen_name=self.session.db["user_name"], target_screen_name=screen_name)
|
||||
self.friendship_status = self.session.twitter.show_friendship(source_screen_name=self.session.db["user_name"], target_screen_name=screen_name)
|
||||
|
||||
def fill_profile_fields(self):
|
||||
self.dialog.set_name(self.data["name"])
|
||||
@@ -81,11 +81,11 @@ class profileController(object):
|
||||
url = self.dialog.get("url")
|
||||
if self.file != None:
|
||||
try:
|
||||
self.session.twitter.twitter.update_profile_image(image=self.file)
|
||||
self.session.twitter.update_profile_image(image=self.file)
|
||||
except TwythonError as e:
|
||||
output.speak(u"Error %s. %s" % (e.error_code, e.msg))
|
||||
try:
|
||||
self.session.twitter.twitter.update_profile(name=name, description=description, location=location, url=url)
|
||||
self.session.twitter.update_profile(name=name, description=description, location=location, url=url)
|
||||
except TwythonError as e:
|
||||
output.speak(u"Error %s. %s" % (e.error_code, e.msg))
|
||||
|
||||
|
@@ -29,43 +29,43 @@ class userActionsController(object):
|
||||
|
||||
def follow(self, user):
|
||||
try:
|
||||
self.session.twitter.twitter.create_friendship(screen_name=user )
|
||||
self.session.twitter.create_friendship(screen_name=user )
|
||||
except TwythonError as err:
|
||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
||||
|
||||
def unfollow(self, user):
|
||||
try:
|
||||
id = self.session.twitter.twitter.destroy_friendship(screen_name=user )
|
||||
id = self.session.twitter.destroy_friendship(screen_name=user )
|
||||
except TwythonError as err:
|
||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
||||
|
||||
def mute(self, user):
|
||||
try:
|
||||
id = self.session.twitter.twitter.create_mute(screen_name=user )
|
||||
id = self.session.twitter.create_mute(screen_name=user )
|
||||
except TwythonError as err:
|
||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
||||
|
||||
def unmute(self, user):
|
||||
try:
|
||||
id = self.session.twitter.twitter.destroy_mute(screen_name=user )
|
||||
id = self.session.twitter.destroy_mute(screen_name=user )
|
||||
except TwythonError as err:
|
||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
||||
|
||||
def report(self, user):
|
||||
try:
|
||||
id = self.session.twitter.twitter.report_spam(screen_name=user )
|
||||
id = self.session.twitter.report_spam(screen_name=user )
|
||||
except TwythonError as err:
|
||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
||||
|
||||
def block(self, user):
|
||||
try:
|
||||
id = self.session.twitter.twitter.create_block(screen_name=user )
|
||||
id = self.session.twitter.create_block(screen_name=user )
|
||||
except TwythonError as err:
|
||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
||||
|
||||
def unblock(self, user):
|
||||
try:
|
||||
id = self.session.twitter.twitter.destroy_block(screen_name=user )
|
||||
id = self.session.twitter.destroy_block(screen_name=user )
|
||||
except TwythonError as err:
|
||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
||||
|
||||
|
@@ -45,7 +45,7 @@ search = string(default="alt+win+-")
|
||||
edit_keystrokes = string(default="alt+win+k")
|
||||
view_user_lists = string(default="alt+win+l")
|
||||
get_more_items = string(default="alt+win+pageup")
|
||||
reverse_geocode = string(default="alt+win+g")
|
||||
reverse_geocode = string(default="control+win+g")
|
||||
view_reverse_geocode = string(default="alt+win+shift+g")
|
||||
get_trending_topics = string(default="control+win+t")
|
||||
check_for_updates = string(default="alt+win+u")
|
||||
|
@@ -5,7 +5,7 @@ import paths
|
||||
import os
|
||||
import logging
|
||||
log = logging.getLogger("sessionmanager.manager")
|
||||
import session_exceptions
|
||||
from sessions import session_exceptions
|
||||
|
||||
manager = None
|
||||
def setup():
|
||||
|
@@ -12,7 +12,8 @@ import paths
|
||||
import time
|
||||
import os
|
||||
import logging
|
||||
import session
|
||||
import sessions
|
||||
from sessions.twitter import session
|
||||
import manager
|
||||
import config_utils
|
||||
import config
|
||||
@@ -76,12 +77,12 @@ class sessionManagerController(object):
|
||||
def do_ok(self):
|
||||
log.debug("Starting sessions...")
|
||||
for i in self.sessions:
|
||||
if session.sessions.has_key(i) == True: continue
|
||||
if sessions.sessions.has_key(i) == True: continue
|
||||
s = session.Session(i)
|
||||
s.get_configuration()
|
||||
if i not in config.app["sessions"]["ignored_sessions"]:
|
||||
s.login()
|
||||
session.sessions[i] = s
|
||||
sessions.sessions[i] = s
|
||||
self.new_sessions[i] = s
|
||||
# self.view.destroy()
|
||||
|
||||
|
@@ -2,6 +2,7 @@
|
||||
import wx
|
||||
from multiplatform_widgets import widgets
|
||||
import application
|
||||
|
||||
class sessionManagerWindow(wx.Dialog):
|
||||
def __init__(self):
|
||||
super(sessionManagerWindow, self).__init__(parent=None, title=_(u"Session manager"), size=wx.DefaultSize)
|
||||
@@ -73,19 +74,4 @@ class sessionManagerWindow(wx.Dialog):
|
||||
self.configuration.Hide()
|
||||
|
||||
def destroy(self):
|
||||
self.Destroy()
|
||||
|
||||
class authorisationDialog(wx.Dialog):
|
||||
def __init__(self):
|
||||
super(authorisationDialog, self).__init__(parent=None, title=_(u"Authorising account..."))
|
||||
panel = wx.Panel(self)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
static = wx.StaticText(panel, wx.NewId(), _(u"Enter your PIN code here"))
|
||||
self.text = wx.TextCtrl(panel, -1)
|
||||
self.ok = wx.Button(panel, wx.ID_OK)
|
||||
self.cancel = wx.Button(panel, wx.ID_CANCEL)
|
||||
sizer.Add(self.text, 0, wx.ALL, 5)
|
||||
sizer.Add(self.cancel, 0, wx.ALL, 5)
|
||||
panel.SetSizer(sizer)
|
||||
min = sizer.CalcMin()
|
||||
self.SetClientSize(min)
|
||||
self.Destroy()
|
5
src/sessions/__init__.py
Normal file
5
src/sessions/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
""" this package contains code related to Sessions.
|
||||
In TWBlue, a session module defines everything a social network needs to be used in the program."""
|
||||
# let's define a global object for storing sessions across the program.
|
||||
sessions = {}
|
116
src/sessions/base.py
Normal file
116
src/sessions/base.py
Normal file
@@ -0,0 +1,116 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
""" A base class to be derived in possible new sessions for TWBlue and services."""
|
||||
import paths
|
||||
import output
|
||||
import time
|
||||
import sound
|
||||
import logging
|
||||
import config_utils
|
||||
import shelve
|
||||
import application
|
||||
import os
|
||||
import session_exceptions as Exceptions
|
||||
log = logging.getLogger("sessionmanager.session")
|
||||
|
||||
class baseSession(object):
|
||||
""" toDo: Decorators does not seem to be working when using them in an inherited class."""
|
||||
|
||||
# Decorators.
|
||||
|
||||
def _require_login(fn):
|
||||
""" Decorator for checking if the user is logged in.
|
||||
Some functions may need this to avoid making unneeded calls."""
|
||||
def f(self, *args, **kwargs):
|
||||
if self.logged == True:
|
||||
fn(self, *args, **kwargs)
|
||||
else:
|
||||
raise Exceptions.NotLoggedSessionError("You are not logged in yet.")
|
||||
return f
|
||||
|
||||
def _require_configuration(fn):
|
||||
""" Check if the user has a configured session."""
|
||||
def f(self, *args, **kwargs):
|
||||
if self.settings != None:
|
||||
fn(self, *args, **kwargs)
|
||||
else:
|
||||
raise Exceptions.NotConfiguredSessionError("Not configured.")
|
||||
return f
|
||||
|
||||
def __init__(self, session_id):
|
||||
""" session_id (str): The name of the folder inside the config directory where the session is located."""
|
||||
super(baseSession, self).__init__()
|
||||
self.session_id = session_id
|
||||
self.logged = False
|
||||
self.settings = None
|
||||
self.db={}
|
||||
|
||||
@property
|
||||
def is_logged(self):
|
||||
return self.logged
|
||||
|
||||
def get_configuration(self):
|
||||
""" Get settings for a session."""
|
||||
file_ = "%s/session.conf" % (self.session_id,)
|
||||
log.debug("Creating config file %s" % (file_,))
|
||||
self.settings = config_utils.load_config(paths.config_path(file_), paths.app_path("Conf.defaults"))
|
||||
self.init_sound()
|
||||
self.deshelve()
|
||||
|
||||
def init_sound(self):
|
||||
try: self.sound = sound.soundSystem(self.settings["sound"])
|
||||
except: pass
|
||||
|
||||
@_require_configuration
|
||||
def login(self, verify_credentials=True):
|
||||
pass
|
||||
|
||||
@_require_configuration
|
||||
def authorise(self):
|
||||
pass
|
||||
|
||||
def shelve(self):
|
||||
"""Shelve the database to allow for persistance."""
|
||||
shelfname=paths.config_path(str(self.session_id)+"/cache.db")
|
||||
if self.settings["general"]["persist_size"] == 0:
|
||||
if os.path.exists(shelfname):
|
||||
os.remove(shelfname)
|
||||
return
|
||||
try:
|
||||
if not os.path.exists(shelfname):
|
||||
output.speak("Generating database, this might take a while.",True)
|
||||
shelf=shelve.open(paths.config_path(shelfname),'c')
|
||||
for key,value in self.db.items():
|
||||
if type(key) != str and type(key) != unicode:
|
||||
output.speak("Uh oh, while shelving the database, a key of type " + str(type(key)) + " has been found. It will be converted to type str, but this will cause all sorts of problems on deshelve. Please bring this to the attention of the " + application.name + " developers immediately. More information about the error will be written to the error log.",True)
|
||||
log.error("Uh oh, " + str(key) + " is of type " + str(type(key)) + "!")
|
||||
# Convert unicode objects to UTF-8 strings before shelve these objects.
|
||||
if type(value) == list and self.settings["general"]["persist_size"] != -1 and len(value) > self.settings["general"]["persist_size"]:
|
||||
shelf[str(key.encode("utf-8"))]=value[self.settings["general"]["persist_size"]:]
|
||||
else:
|
||||
shelf[str(key.encode("utf-8"))]=value
|
||||
shelf.close()
|
||||
except:
|
||||
output.speak("An exception occurred while shelving the " + application.name + " database. It will be deleted and rebuilt automatically. If this error persists, send the error log to the " + application.name + " developers.",True)
|
||||
log.exception("Exception while shelving" + shelfname)
|
||||
os.remove(shelfname)
|
||||
|
||||
def deshelve(self):
|
||||
"""Import a shelved database."""
|
||||
shelfname=paths.config_path(str(self.session_id)+"/cache.db")
|
||||
if self.settings["general"]["persist_size"] == 0:
|
||||
if os.path.exists(shelfname):
|
||||
os.remove(shelfname)
|
||||
return
|
||||
try:
|
||||
shelf=shelve.open(paths.config_path(shelfname),'c')
|
||||
for key,value in shelf.items():
|
||||
self.db[key]=value
|
||||
shelf.close()
|
||||
except:
|
||||
output.speak("An exception occurred while deshelving the " + application.name + " database. It will be deleted and rebuilt automatically. If this error persists, send the error log to the " + application.name + " developers.",True)
|
||||
log.exception("Exception while deshelving" + shelfname)
|
||||
try:
|
||||
os.remove(shelfname)
|
||||
except:
|
||||
pass
|
||||
|
1
src/sessions/twitter/__init__.py
Normal file
1
src/sessions/twitter/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
@@ -75,35 +75,6 @@ def compose_tweet(tweet, db, relative_times, show_screen_names=False, session=No
|
||||
if config.app['app-settings']['handle_longtweets']: pass
|
||||
return [user+", ", text, ts+", ", source]
|
||||
|
||||
def compose_dm(tweet, db, relative_times, 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."""
|
||||
if system == "Windows":
|
||||
original_date = arrow.get(tweet["created_at"], "ddd MMM DD H:m:s Z YYYY", locale="en")
|
||||
if relative_times == True:
|
||||
ts = original_date.humanize(locale=languageHandler.getLanguage())
|
||||
else:
|
||||
ts = original_date.replace(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.getLanguage())
|
||||
else:
|
||||
ts = tweet["created_at"]
|
||||
text = StripChars(tweet["text"])
|
||||
source = "DM"
|
||||
if db["user_name"] == tweet["sender"]["screen_name"]:
|
||||
if show_screen_names:
|
||||
user = _(u"Dm to %s ") % (tweet["recipient"]["screen_name"],)
|
||||
else:
|
||||
user = _(u"Dm to %s ") % (tweet["recipient"]["name"],)
|
||||
else:
|
||||
if show_screen_names:
|
||||
user = tweet["sender"]["screen_name"]
|
||||
else:
|
||||
user = tweet["sender"]["name"]
|
||||
if text[-1] in chars: text=text+"."
|
||||
urls = utils.find_urls_in_text(text)
|
||||
for url in range(0, len(urls)):
|
||||
try: text = text.replace(urls[url], tweet["entities"]["urls"][url]["expanded_url"])
|
||||
except IndexError: pass
|
||||
return [user+", ", text, ts+", ", source]
|
||||
|
||||
def compose_direct_message(item, db, relative_times, show_screen_names=False, session=None):
|
||||
# for a while this function will be together with compose_dm.
|
||||
# this one composes direct messages based on events (new API Endpoints).
|
||||
@@ -193,58 +164,6 @@ def compose_followers_list(tweet, db, relative_times=True, show_screen_names=Fal
|
||||
ts2 = _("Unavailable")
|
||||
return [_(u"%s (@%s). %s followers, %s friends, %s tweets. Last tweeted %s. Joined Twitter %s") % (tweet["name"], tweet["screen_name"], tweet["followers_count"], tweet["friends_count"], tweet["statuses_count"], ts2, ts)]
|
||||
|
||||
def compose_event(data, username, show_screen_names=False, session=None):
|
||||
if show_screen_names:
|
||||
value = "screen_name"
|
||||
else:
|
||||
value = "name"
|
||||
if data["event"] == "block":
|
||||
event = _("You've blocked %s") % (data["target"][value])
|
||||
elif data["event"] == "unblock":
|
||||
event = _(u"You've unblocked %s") % (data["target"][value])
|
||||
elif data["event"] == "follow":
|
||||
if data["target"]["screen_name"] == username:
|
||||
event = _(u"%s(@%s) has followed you") % (data["source"]["name"], data["source"]["screen_name"])
|
||||
elif data["source"]["screen_name"] == username:
|
||||
event = _(u"You've followed %s(@%s)") % (data["target"]["name"], data["target"]["screen_name"])
|
||||
elif data["event"] == "unfollow":
|
||||
event = _(u"You've unfollowed %s (@%s)") % (data["target"]["name"], data["target"]["screen_name"])
|
||||
elif data["event"] == "favorite":
|
||||
if data["source"]["screen_name"] == username:
|
||||
event = _(u"You've liked: %s, %s") % (data["target"][value], data["target_object"]["text"])
|
||||
else:
|
||||
event = _(u"%s(@%s) has liked: %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["text"])
|
||||
elif data["event"] == "unfavorite":
|
||||
if data["source"]["screen_name"] == username: event = _(u"You've unliked: %s, %s") % (data["target"][value], data["target_object"]["text"])
|
||||
else: event = _(u"%s(@%s) has unliked: %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["text"])
|
||||
elif data["event"] == "list_created":
|
||||
event = _(u"You've created the list %s") % (data["target_object"]["name"])
|
||||
elif data["event"] == "list_destroyed":
|
||||
event = _("You've deleted the list %s") % (data["target_object"]["name"])
|
||||
elif data["event"] == "list_updated":
|
||||
event = _("You've updated the list %s") % (data["target_object"]["name"])
|
||||
elif data["event"] == "list_member_added":
|
||||
if data["source"]["screen_name"] == username: event = _(u"You've added %s(@%s) to the list %s") % (data["target"]["name"], data["target"]["screen_name"], data["target_object"]["name"])
|
||||
else: event = _(u"%s(@%s) has added you to the list %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["name"])
|
||||
elif data["event"] == "list_member_removed":
|
||||
if data["source"]["screen_name"] == username: event = _(u"You'be removed %s(@%s) from the list %s") % (data["target"]["name"], data["target"]["screen_name"], data["target_object"]["name"])
|
||||
else: event = _(u"%s(@%s) has removed you from the list %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["name"])
|
||||
elif data["event"] == "list_user_subscribed":
|
||||
if data["source"]["screen_name"] == username: event = _(u"You've subscribed to the list %s, which is owned by %s(@%s)") % (data["target_object"]["name"], data["target"]["name"], data["target"]["screen_name"])
|
||||
else: event = _(u"%s(@%s) has subscribed you to the list %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["name"])
|
||||
elif data["event"] == "list_user_unsubscribed":
|
||||
if data["source"]["screen_name"] == username: event = _(u"You've unsubscribed from the list %s, which is owned by %s(@%s)") % (data["target_object"]["name"], data["target"]["name"], data["target"]["screen_name"])
|
||||
else: event = _("You've been unsubscribed from the list %s, which is owned by %s(@%s)") % (data["target_object"]["name"], data["source"]["name"], data["source"]["screen_name"])
|
||||
elif data["event"] == "retweeted_retweet":
|
||||
if data["source"]["screen_name"] == username: event = _(u"You have retweeted a retweet from %s(@%s): %s") % (data["target"]["name"], data["target"]["screen_name"], data["target_object"]["retweeted_status"]["text"])
|
||||
else: event = _(u"%s(@%s) has retweeted your retweet: %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["retweeted_status"]["text"])
|
||||
elif data["event"] == "quoted_tweet":
|
||||
event = _(u"@{0} quoted your tweet: {1}").format(data["source"]["screen_name"], data["target_object"]["text"])
|
||||
else:
|
||||
event = _("Unknown")
|
||||
log.error("event: %s\n target: %s\n source: %s\n target_object: %s" % (data["event"], data["target"], data["source"], data["target_object"]))
|
||||
return [time.strftime("%I:%M %p"), event]
|
||||
|
||||
def compose_list(list):
|
||||
name = list["name"]
|
||||
if list["description"] == None: description = _(u"No description available")
|
2
src/sessions/twitter/long_tweets/__init__.py
Normal file
2
src/sessions/twitter/long_tweets/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
""" this package holds different modules to extract information regarding long tweets. A long tweet contains more than one tweet (such a quoted tweet), or is made via services like twishort."""
|
@@ -16,9 +16,12 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
############################################################
|
||||
from twitter import utils
|
||||
from sessions.twitter import utils
|
||||
|
||||
def is_long(tweet):
|
||||
""" Check if the passed tweet contains a quote in its metadata.
|
||||
tweet dict: a tweet dictionary.
|
||||
returns True if a quote is detected, False otherwise."""
|
||||
if tweet.has_key("quoted_status_id") and tweet.has_key("quoted_status"):
|
||||
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"):
|
||||
@@ -26,6 +29,9 @@ def is_long(tweet):
|
||||
return False
|
||||
|
||||
def clear_url(tweet):
|
||||
""" Reads data from a quoted tweet and removes the link to the Status from the tweet's text.
|
||||
tweet dict: a tweet dictionary.
|
||||
returns a tweet dictionary without the URL to the status ID in its text to display."""
|
||||
if tweet.has_key("retweeted_status"):
|
||||
if tweet["retweeted_status"].has_key("full_text"):
|
||||
value = "full_text"
|
@@ -16,20 +16,26 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
############################################################
|
||||
import logging
|
||||
import requests
|
||||
import keys
|
||||
import logging
|
||||
log = logging.getLogger("long_tweets.twishort")
|
||||
from twitter import utils
|
||||
from requests_oauthlib import OAuth1Session
|
||||
from sessions.twitter import utils
|
||||
|
||||
log = logging.getLogger("long_tweets.twishort")
|
||||
|
||||
def get_twishort_uri(url):
|
||||
""" Takes A twishort URl and returns the twishort ID.
|
||||
url str: an url like http://twishort.com/id.
|
||||
returns a twishort ID if the URL is valid, False otherwise."""
|
||||
try:
|
||||
return url.split("twishort.com/")[1]
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
def is_long(tweet):
|
||||
""" Check if the passed tweet is made with Twishort.
|
||||
returns True if is a long tweet, False otherwise."""
|
||||
long = False
|
||||
for url in range(0, len(tweet["entities"]["urls"])):
|
||||
try:
|
||||
@@ -53,17 +59,25 @@ def is_long(tweet):
|
||||
return long
|
||||
|
||||
def get_full_text(uri):
|
||||
""" Get Twishort's full text.
|
||||
uri str: Twishort's identifier.
|
||||
returns the contents of the tweet."""
|
||||
try:
|
||||
r = requests.get("http://api.twishort.com/1.1/get.json", params={"uri": uri, "api_key": keys.keyring.get("twishort_api_key")})
|
||||
msg = r.json()["text"]
|
||||
# Try to parse possible HTML entities.
|
||||
from twitter.compose import StripChars
|
||||
from sessions.twitter.compose import StripChars
|
||||
msg = StripChars(msg)
|
||||
return msg
|
||||
except:
|
||||
return False
|
||||
|
||||
def create_tweet(user_token, user_secret, text, media=0):
|
||||
""" Send a tweet to be extended by using Twishort.
|
||||
user_token, user_secret str: Twitter user access key and secret, used by TWBlue to authorise against Twitter.
|
||||
text str: Tweet text, max 10000 characters.
|
||||
media int: Not used currently.
|
||||
Returns text to be placed in the Tweet if the post has been succeeded, 0 otherwise."""
|
||||
twitter = OAuth1Session(keys.keyring.get("api_key"), client_secret=keys.keyring.get("api_secret"), resource_owner_key=user_token, resource_owner_secret=user_secret)
|
||||
twishort_key=keys.keyring.get("twishort_api_key")
|
||||
x_auth_service_provider = "https://api.twitter.com/1.1/account/verify_credentials.json"
|
||||
@@ -84,4 +98,4 @@ def create_tweet(user_token, user_secret, text, media=0):
|
||||
return response.json()["text_to_tweet"]
|
||||
except:
|
||||
print "There was a problem creating a long tweet"
|
||||
return 0
|
||||
return 0
|
@@ -1,65 +1,33 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
""" The main session object. Here are the twitter functions to interact with the "model" of TWBlue."""
|
||||
import wx
|
||||
import urllib2
|
||||
import config
|
||||
import twitter
|
||||
from keys import keyring
|
||||
import session_exceptions as Exceptions
|
||||
import paths
|
||||
import output
|
||||
import time
|
||||
import sound
|
||||
import logging
|
||||
from twitter import utils, compose
|
||||
from twython import TwythonError, TwythonRateLimitError, TwythonAuthError
|
||||
import config_utils
|
||||
import shelve
|
||||
import application
|
||||
""" This is the main session needed to access all Twitter Features."""
|
||||
import os
|
||||
from mysc.thread_utils import stream_threaded, call_threaded
|
||||
import time
|
||||
import logging
|
||||
import webbrowser
|
||||
import wx
|
||||
import config
|
||||
import output
|
||||
import application
|
||||
from pubsub import pub
|
||||
log = logging.getLogger("sessionmanager.session")
|
||||
from long_tweets import tweets, twishort
|
||||
from twython import Twython, TwythonError, TwythonRateLimitError, TwythonAuthError
|
||||
from mysc.thread_utils import call_threaded
|
||||
from keys import keyring
|
||||
from sessions import base
|
||||
from sessions.twitter import utils, compose
|
||||
from sessions.twitter.long_tweets import tweets, twishort
|
||||
from wxUI import authorisationDialog
|
||||
|
||||
sessions = {}
|
||||
log = logging.getLogger("sessions.twitterSession")
|
||||
|
||||
class Session(object):
|
||||
class Session(base.baseSession):
|
||||
""" A session object where we will save configuration, the twitter object and a local storage for saving the items retrieved through the Twitter API methods"""
|
||||
|
||||
# Decorators.
|
||||
|
||||
def _require_login(fn):
|
||||
|
||||
""" Decorator for checking if the user is logged in(a twitter object has credentials) on twitter.
|
||||
Some functions may need this to avoid making unneeded twitter API calls."""
|
||||
|
||||
def f(self, *args, **kwargs):
|
||||
if self.logged == True:
|
||||
fn(self, *args, **kwargs)
|
||||
else:
|
||||
raise Exceptions.NotLoggedSessionError("You are not logged in yet.")
|
||||
return f
|
||||
|
||||
def _require_configuration(fn):
|
||||
|
||||
""" Check if the user has a configured session."""
|
||||
|
||||
def f(self, *args, **kwargs):
|
||||
if self.settings != None:
|
||||
fn(self, *args, **kwargs)
|
||||
else:
|
||||
raise Exceptions.NotConfiguredSessionError("Not configured.")
|
||||
return f
|
||||
|
||||
def order_buffer(self, name, data, ignore_older=True):
|
||||
|
||||
""" Put the new items in the local database.
|
||||
""" Put new items in the local database.
|
||||
name str: The name for the buffer stored in the dictionary.
|
||||
data list: A list with tweets.
|
||||
ignore_older bool: if set to True, items older than the first element on the list will be ignored.
|
||||
returns the number of items that have been added in this execution"""
|
||||
|
||||
num = 0
|
||||
last_id = None
|
||||
if self.db.has_key(name) == False:
|
||||
@@ -89,18 +57,18 @@ class Session(object):
|
||||
return num
|
||||
|
||||
def order_cursored_buffer(self, name, data):
|
||||
|
||||
""" Put the new items on the local database. Useful for cursored buffers (followers, friends, users of a list and searches)
|
||||
""" Put new items on the local database. Useful for cursored buffers (followers, friends, users of a list and searches)
|
||||
name str: The name for the buffer stored in the dictionary.
|
||||
data list: A list with items and some information about cursors.
|
||||
returns the number of items that have been added in this execution"""
|
||||
# Direct messages should be added to db in other function.
|
||||
# Because they will be populating two buffers with one endpoint.
|
||||
if name == "direct_messages":
|
||||
return self.order_direct_messages(data)
|
||||
num = 0
|
||||
if self.db.has_key(name) == False:
|
||||
self.db[name] = {}
|
||||
self.db[name]["items"] = []
|
||||
# if len(self.db[name]["items"]) > 0:
|
||||
for i in data:
|
||||
if utils.find_item(i["id"], self.db[name]["items"]) == None:
|
||||
if self.settings["general"]["reverse_timelines"] == False: self.db[name]["items"].append(i)
|
||||
@@ -109,6 +77,9 @@ class Session(object):
|
||||
return num
|
||||
|
||||
def order_direct_messages(self, data):
|
||||
""" Add incoming and sent direct messages to their corresponding database items.
|
||||
data list: A list of direct messages to add.
|
||||
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
|
||||
sent = 0
|
||||
if self.db.has_key("direct_messages") == False:
|
||||
@@ -116,7 +87,7 @@ class Session(object):
|
||||
self.db["direct_messages"]["items"] = []
|
||||
for i in data:
|
||||
if i["message_create"]["sender_id"] == self.db["user_id"]:
|
||||
if utils.find_item(i["id"], self.db["sent_direct_messages"]["items"]) == None:
|
||||
if self.db.has_key("sent_direct_messages") 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)
|
||||
else: self.db["sent_direct_messages"]["items"].insert(0, i)
|
||||
sent = sent+1
|
||||
@@ -128,104 +99,95 @@ class Session(object):
|
||||
pub.sendMessage("sent-dms-updated", total=sent, account=self.db["user_name"])
|
||||
return incoming
|
||||
|
||||
def __init__(self, session_id):
|
||||
|
||||
""" session_id (str): The name of the folder inside the config directory where the session is located."""
|
||||
|
||||
super(Session, self).__init__()
|
||||
self.session_id = session_id
|
||||
self.logged = False
|
||||
self.settings = None
|
||||
self.twitter = twitter.twitter.twitter()
|
||||
self.db={}
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Session, self).__init__(*args, **kwargs)
|
||||
self.reconnection_function_active = False
|
||||
self.counter = 0
|
||||
self.lists = []
|
||||
pub.subscribe(self.add_friends, "friends-receibed")
|
||||
|
||||
@property
|
||||
def is_logged(self):
|
||||
return self.logged
|
||||
|
||||
def get_configuration(self):
|
||||
|
||||
""" Gets settings for a session."""
|
||||
|
||||
file_ = "%s/session.conf" % (self.session_id,)
|
||||
# try:
|
||||
log.debug("Creating config file %s" % (file_,))
|
||||
self.settings = config_utils.load_config(paths.config_path(file_), paths.app_path("Conf.defaults"))
|
||||
self.init_sound()
|
||||
self.deshelve()
|
||||
# except:
|
||||
# log.exception("The session configuration has failed.")
|
||||
# self.settings = None
|
||||
|
||||
def init_sound(self):
|
||||
try: self.sound = sound.soundSystem(self.settings["sound"])
|
||||
except: pass
|
||||
|
||||
@_require_configuration
|
||||
# @_require_configuration
|
||||
def login(self, verify_credentials=True):
|
||||
|
||||
""" Log into twitter using credentials from settings.
|
||||
if the user account isn't authorised, it needs to call self.authorise() before login."""
|
||||
|
||||
if self.settings["twitter"]["user_key"] != None and self.settings["twitter"]["user_secret"] != None:
|
||||
try:
|
||||
log.debug("Logging in to twitter...")
|
||||
self.twitter.login(self.settings["twitter"]["user_key"], self.settings["twitter"]["user_secret"], verify_credentials)
|
||||
self.twitter = Twython(keyring.get("api_key"), keyring.get("api_secret"), self.settings["twitter"]["user_key"], self.settings["twitter"]["user_secret"])
|
||||
if verify_credentials == True:
|
||||
self.credentials = self.twitter.verify_credentials()
|
||||
self.logged = True
|
||||
log.debug("Logged.")
|
||||
self.counter = 0
|
||||
except:
|
||||
except IOError:
|
||||
log.error("The login attempt failed.")
|
||||
self.logged = False
|
||||
else:
|
||||
self.logged = False
|
||||
raise Exceptions.RequireCredentialsSessionError
|
||||
|
||||
@_require_configuration
|
||||
# @_require_configuration
|
||||
def authorise(self):
|
||||
|
||||
""" Authorises a Twitter account. This function needs to be called for each new session, after self.get_configuration() and before self.login()"""
|
||||
|
||||
if self.logged == True:
|
||||
raise Exceptions.AlreadyAuthorisedError("The authorisation process is not needed at this time.")
|
||||
else:
|
||||
self.twitter.authorise()
|
||||
twitter = Twython(keyring.get("api_key"), keyring.get("api_secret"))
|
||||
self.auth = twitter.get_authentication_tokens(callback_url="oob")
|
||||
webbrowser.open_new_tab(self.auth['auth_url'])
|
||||
self.authorisation_dialog = authorisationDialog()
|
||||
self.authorisation_dialog.cancel.Bind(wx.EVT_BUTTON, self.authorisation_cancelled)
|
||||
self.authorisation_dialog.ok.Bind(wx.EVT_BUTTON, self.authorisation_accepted)
|
||||
self.authorisation_dialog.ShowModal()
|
||||
|
||||
def verify_authorisation(self, pincode):
|
||||
twitter = Twython(keyring.get("api_key"), keyring.get("api_secret"), self.auth['oauth_token'], self.auth['oauth_token_secret'])
|
||||
final = twitter.get_authorized_tokens(pincode)
|
||||
self.settings["twitter"]["user_key"] = final["oauth_token"]
|
||||
self.settings["twitter"]["user_secret"] = final["oauth_token_secret"]
|
||||
self.settings.write()
|
||||
del self.auth
|
||||
|
||||
def authorisation_cancelled(self, *args, **kwargs):
|
||||
""" Destroy the authorization dialog. """
|
||||
self.authorisation_dialog.Destroy()
|
||||
del self.authorisation_dialog
|
||||
|
||||
def authorisation_accepted(self, *args, **kwargs):
|
||||
""" Gets the PIN code entered by user and validate it through Twitter."""
|
||||
pincode = self.authorisation_dialog.text.GetValue()
|
||||
self.twitter.verify_authorisation(self.settings, pincode)
|
||||
self.verify_authorisation(pincode)
|
||||
self.authorisation_dialog.Destroy()
|
||||
|
||||
def get_more_items(self, update_function, users=False, dm=False, name=None, *args, **kwargs):
|
||||
""" Get more items for twitter objects.
|
||||
update_function str: function to call for getting more items. Must be member of self.twitter.
|
||||
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."""
|
||||
results = []
|
||||
data = getattr(self.twitter.twitter, update_function)(*args, **kwargs)
|
||||
if kwargs.has_key("cursor") 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)
|
||||
if users == True:
|
||||
if type(data) == dict and data.has_key("next_cursor"):
|
||||
self.db[name]["cursor"] = data["next_cursor"]
|
||||
if data.has_key("next_cursor"): # 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)
|
||||
elif type(data) == list:
|
||||
results.extend(data[1:])
|
||||
elif dm == True:
|
||||
self.db[name]["cursor"] = data["next_cursor"]
|
||||
if data.has_key("next_cursor"): # 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)
|
||||
else:
|
||||
results.extend(data[1:])
|
||||
return results
|
||||
|
||||
def api_call(self, call_name, action="", _sound=None, report_success=False, report_failure=True, preexec_message="", *args, **kwargs):
|
||||
|
||||
""" Make a call to the Twitter API. If there is a connectionError or another exception not related to Twitter, It will call the method again at least 25 times, waiting a while between calls. Useful for post methods.
|
||||
If twitter returns an error, it will not call the method anymore.
|
||||
call_name str: The method to call
|
||||
@@ -234,17 +196,17 @@ class Session(object):
|
||||
_sound str: a sound to play if the call is executed properly.
|
||||
report_success and report_failure bool: These are self explanatory. True or False.
|
||||
preexec_message str: A message to speak to the user while the method is running, example: "trying to follow x user"."""
|
||||
|
||||
finished = False
|
||||
tries = 0
|
||||
if preexec_message:
|
||||
output.speak(preexec_message, True)
|
||||
while finished==False and tries < 25:
|
||||
try:
|
||||
val = getattr(self.twitter.twitter, call_name)(*args, **kwargs)
|
||||
val = getattr(self.twitter, call_name)(*args, **kwargs)
|
||||
finished = True
|
||||
except TwythonError as e:
|
||||
output.speak(e.message)
|
||||
val = None
|
||||
if e.error_code != 403 and e.error_code != 404:
|
||||
tries = tries+1
|
||||
time.sleep(5)
|
||||
@@ -260,50 +222,45 @@ class Session(object):
|
||||
return val
|
||||
|
||||
def search(self, name, *args, **kwargs):
|
||||
tl = self.twitter.twitter.search(*args, **kwargs)
|
||||
""" Search in twitter, passing args and kwargs as arguments to the Twython function."""
|
||||
tl = self.twitter.search(*args, **kwargs)
|
||||
tl["statuses"].reverse()
|
||||
return tl["statuses"]
|
||||
|
||||
@_require_login
|
||||
# @_require_login
|
||||
def get_favourites_timeline(self, name, *args, **kwargs):
|
||||
|
||||
""" Gets favourites for the authenticated user or a friend or follower.
|
||||
name str: Name for storage in the database."""
|
||||
|
||||
tl = self.call_paged(self.twitter.twitter.get_favorites, *args, **kwargs)
|
||||
name str: Name for storage in the database.
|
||||
args and kwargs are passed directly to the Twython function."""
|
||||
tl = self.call_paged("get_favorites", *args, **kwargs)
|
||||
return self.order_buffer(name, tl)
|
||||
|
||||
def call_paged(self, update_function, *args, **kwargs):
|
||||
|
||||
""" Makes a call to the Twitter API methods several times. Useful for get methods.
|
||||
this function is needed for retrieving more than 200 items.
|
||||
update_function str: The function to call. This function must be child of self.twitter.twitter
|
||||
update_function str: The function to call. This function must be child of self.twitter
|
||||
args and kwargs are passed to update_function.
|
||||
returns a list with all items retrieved."""
|
||||
|
||||
if application.streaming_lives():
|
||||
max = int(self.settings["general"]["max_api_calls"])-1
|
||||
else:
|
||||
max = 0
|
||||
max = 0
|
||||
results = []
|
||||
data = getattr(self.twitter.twitter, update_function)(count=self.settings["general"]["max_tweets_per_call"], *args, **kwargs)
|
||||
data = getattr(self.twitter, update_function)(count=self.settings["general"]["max_tweets_per_call"], *args, **kwargs)
|
||||
results.extend(data)
|
||||
for i in range(0, max):
|
||||
if i == 0: max_id = results[-1]["id"]
|
||||
else: max_id = results[0]["id"]
|
||||
data = getattr(self.twitter.twitter, update_function)(max_id=max_id, count=self.settings["general"]["max_tweets_per_call"], *args, **kwargs)
|
||||
data = getattr(self.twitter, update_function)(max_id=max_id, count=self.settings["general"]["max_tweets_per_call"], *args, **kwargs)
|
||||
results.extend(data)
|
||||
results.reverse()
|
||||
return results
|
||||
|
||||
@_require_login
|
||||
# @_require_login
|
||||
def get_user_info(self):
|
||||
|
||||
""" Retrieves some information required by TWBlue for setup."""
|
||||
f = self.twitter.twitter.get_account_settings()
|
||||
f = self.twitter.get_account_settings()
|
||||
sn = f["screen_name"]
|
||||
self.settings["twitter"]["user_name"] = sn
|
||||
self.db["user_name"] = sn
|
||||
self.db["user_id"] = self.twitter.twitter.show_user(screen_name=sn)["id_str"]
|
||||
self.db["user_id"] = self.twitter.show_user(screen_name=sn)["id_str"]
|
||||
try:
|
||||
self.db["utc_offset"] = f["time_zone"]["utc_offset"]
|
||||
except KeyError:
|
||||
@@ -311,32 +268,26 @@ class Session(object):
|
||||
# Get twitter's supported languages and save them in a global variable
|
||||
#so we won't call to this method once per session.
|
||||
if len(application.supported_languages) == 0:
|
||||
application.supported_languages = self.twitter.twitter.get_supported_languages()
|
||||
application.supported_languages = self.twitter.get_supported_languages()
|
||||
self.get_lists()
|
||||
self.get_muted_users()
|
||||
self.settings.write()
|
||||
|
||||
@_require_login
|
||||
# @_require_login
|
||||
def get_lists(self):
|
||||
|
||||
""" Gets the lists that the user is subscribed to and stores them in the database. Returns None."""
|
||||
|
||||
self.db["lists"] = self.twitter.twitter.show_lists(reverse=True)
|
||||
self.db["lists"] = self.twitter.show_lists(reverse=True)
|
||||
|
||||
@_require_login
|
||||
# @_require_login
|
||||
def get_muted_users(self):
|
||||
|
||||
""" Gets muted users (oh really?)."""
|
||||
self.db["muted_users"] = self.twitter.list_mute_ids()["ids"]
|
||||
|
||||
self.db["muted_users"] = self.twitter.twitter.list_mute_ids()["ids"]
|
||||
|
||||
@_require_login
|
||||
# @_require_login
|
||||
def get_stream(self, name, function, *args, **kwargs):
|
||||
|
||||
""" Retrieves the items for a regular stream.
|
||||
name str: Name to save items to the database.
|
||||
function str: A function to get the items."""
|
||||
|
||||
last_id = -1
|
||||
if self.db.has_key(name):
|
||||
try:
|
||||
@@ -350,13 +301,12 @@ class Session(object):
|
||||
self.order_buffer(name, tl)
|
||||
|
||||
def get_cursored_stream(self, name, function, items="users", get_previous=False, *args, **kwargs):
|
||||
|
||||
""" Gets items for API calls that require using cursors to paginate the results.
|
||||
name str: Name to save it in the database.
|
||||
function str: Function that provides the items.
|
||||
items: When the function returns the list with results, items will tell how the order function should be look.
|
||||
for example get_followers_list returns a list and users are under list["users"], here the items should point to "users"."""
|
||||
|
||||
items: When the function returns the list with results, items will tell how the order function should be look. for example get_followers_list returns a list and users are under list["users"], here the items should point to "users".
|
||||
get_previous bool: wether this function will be used to get previous items in a buffer or load the buffer from scratch.
|
||||
returns number of items retrieved."""
|
||||
items_ = []
|
||||
try:
|
||||
if self.db[name].has_key("cursor") and get_previous:
|
||||
@@ -366,143 +316,33 @@ class Session(object):
|
||||
except KeyError:
|
||||
cursor = -1
|
||||
if cursor != -1:
|
||||
tl = getattr(self.twitter.twitter, function)(cursor=cursor, count=self.settings["general"]["max_tweets_per_call"], *args, **kwargs)
|
||||
tl = getattr(self.twitter, function)(cursor=cursor, count=self.settings["general"]["max_tweets_per_call"], *args, **kwargs)
|
||||
else:
|
||||
tl = getattr(self.twitter.twitter, function)(count=self.settings["general"]["max_tweets_per_call"], *args, **kwargs)
|
||||
tl = getattr(self.twitter, function)(count=self.settings["general"]["max_tweets_per_call"], *args, **kwargs)
|
||||
tl[items].reverse()
|
||||
num = self.order_cursored_buffer(name, tl[items])
|
||||
# Recently, Twitter's new endpoints have cursor if there are more results.
|
||||
if tl.has_key("next_cursor"):
|
||||
self.db[name]["cursor"] = tl["next_cursor"]
|
||||
else:
|
||||
self.db[name]["cursor"] = 0
|
||||
return num
|
||||
|
||||
def start_streaming(self):
|
||||
|
||||
""" Start the streaming for sending tweets in realtime."""
|
||||
if application.streaming_lives():
|
||||
if not hasattr(self, "main_stream"):
|
||||
self.get_timelines()
|
||||
if not hasattr(self, "timelinesStream"):
|
||||
self.get_main_stream()
|
||||
|
||||
def get_main_stream(self):
|
||||
if application.streaming_lives():
|
||||
log.debug("Starting the main stream...")
|
||||
self.main_stream = twitter.buffers.stream.streamer(keyring.get("api_key"), keyring.get("api_secret"), self.settings["twitter"]["user_key"], self.settings["twitter"]["user_secret"], self)
|
||||
stream_threaded(self.main_stream.user, self.session_id)
|
||||
|
||||
def get_timelines(self):
|
||||
if application.streaming_lives():
|
||||
log.debug("Starting the timelines stream...")
|
||||
self.timelinesStream = twitter.buffers.indibidual.timelinesStreamer(keyring.get("api_key"), keyring.get("api_secret"), self.settings["twitter"]["user_key"], self.settings["twitter"]["user_secret"], session=self)
|
||||
ids = ""
|
||||
for i in self.settings["other_buffers"]["timelines"]:
|
||||
ids = ids + "%s, " % (self.db[i+"-timeline"][0]["user"]["id_str"])
|
||||
for i in self.lists:
|
||||
for z in i.users:
|
||||
ids += str(z) + ", "
|
||||
if ids != "":
|
||||
stream_threaded(self.timelinesStream.statuses.filter, self.session_id, follow=ids)
|
||||
|
||||
def add_friends(self):
|
||||
if application.streaming_lives():
|
||||
try:
|
||||
self.timelinesStream.set_friends(self.main_stream.friends)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def listen_stream_error(self):
|
||||
if hasattr(self, "main_stream") and application.streaming_lives():
|
||||
log.debug("Disconnecting the main stream...")
|
||||
self.main_stream.disconnect()
|
||||
del self.main_stream
|
||||
if hasattr(self, "timelinesStream") and application.streaming_lives():
|
||||
log.debug("disconnecting the timelines stream...")
|
||||
self.timelinesStream.disconnect()
|
||||
del self.timelinesStream
|
||||
|
||||
def check_connection(self):
|
||||
""" Restart the Twitter object every 5 executions. It is useful for dealing with requests timeout and other oddities."""
|
||||
log.debug("Executing check connection...")
|
||||
instan = 0
|
||||
self.counter += 1
|
||||
if self.counter >= 4:
|
||||
log.debug("Restarting connection after 5 minutes.")
|
||||
del self.twitter
|
||||
self.logged = False
|
||||
self.twitter = twitter.twitter.twitter()
|
||||
self.login(False)
|
||||
self.counter = 0
|
||||
if self.reconnection_function_active == True: return
|
||||
self.reconnection_function_active = True
|
||||
if not hasattr(self, "main_stream") and application.streaming_lives():
|
||||
self.get_main_stream()
|
||||
if not hasattr(self, "timelinesStream") and application.streaming_lives():
|
||||
self.get_timelines()
|
||||
self.reconnection_function_active = False
|
||||
if hasattr(self, "timelinesStream") and not hasattr(self.timelinesStream, "friends"):
|
||||
self.add_friends()
|
||||
# try:
|
||||
# urllib2.urlopen("http://74.125.228.231", timeout=5)
|
||||
# except urllib2.URLError:
|
||||
# pub.sendMessage("stream-error", session=self.session_id)
|
||||
|
||||
def remove_stream(self, stream):
|
||||
if application.streaming_lives():
|
||||
if stream == "timelinesStream":
|
||||
if hasattr(self, "timelinesStream"):
|
||||
self.timelinesStream.disconnect()
|
||||
del self.timelinesStream
|
||||
else:
|
||||
self.main_stream.disconnect()
|
||||
del self.main_stream
|
||||
|
||||
def shelve(self):
|
||||
"Shelve the database to allow for persistance."
|
||||
shelfname=paths.config_path(str(self.session_id)+"/cache.db")
|
||||
if self.settings["general"]["persist_size"] == 0:
|
||||
if os.path.exists(shelfname):
|
||||
os.remove(shelfname)
|
||||
return
|
||||
try:
|
||||
if not os.path.exists(shelfname):
|
||||
output.speak("Generating database, this might take a while.",True)
|
||||
shelf=shelve.open(paths.config_path(shelfname),'c')
|
||||
for key,value in self.db.items():
|
||||
if type(key) != str and type(key) != unicode:
|
||||
output.speak("Uh oh, while shelving the database, a key of type " + str(type(key)) + " has been found. It will be converted to type str, but this will cause all sorts of problems on deshelve. Please bring this to the attention of the " + application.name + " developers immediately. More information about the error will be written to the error log.",True)
|
||||
log.error("Uh oh, " + str(key) + " is of type " + str(type(key)) + "!")
|
||||
# Convert unicode objects to UTF-8 strings before shelve these objects.
|
||||
if type(value) == list and self.settings["general"]["persist_size"] != -1 and len(value) > self.settings["general"]["persist_size"]:
|
||||
shelf[str(key.encode("utf-8"))]=value[self.settings["general"]["persist_size"]:]
|
||||
else:
|
||||
shelf[str(key.encode("utf-8"))]=value
|
||||
shelf.close()
|
||||
except:
|
||||
output.speak("An exception occurred while shelving the " + application.name + " database. It will be deleted and rebuilt automatically. If this error persists, send the error log to the " + application.name + " developers.",True)
|
||||
log.exception("Exception while shelving" + shelfname)
|
||||
os.remove(shelfname)
|
||||
|
||||
def deshelve(self):
|
||||
"Import a shelved database."
|
||||
shelfname=paths.config_path(str(self.session_id)+"/cache.db")
|
||||
if self.settings["general"]["persist_size"] == 0:
|
||||
if os.path.exists(shelfname):
|
||||
os.remove(shelfname)
|
||||
return
|
||||
try:
|
||||
shelf=shelve.open(paths.config_path(shelfname),'c')
|
||||
for key,value in shelf.items():
|
||||
self.db[key]=value
|
||||
shelf.close()
|
||||
except:
|
||||
output.speak("An exception occurred while deshelving the " + application.name + " database. It will be deleted and rebuilt automatically. If this error persists, send the error log to the " + application.name + " developers.",True)
|
||||
log.exception("Exception while deshelving" + shelfname)
|
||||
try:
|
||||
os.remove(shelfname)
|
||||
except:
|
||||
pass
|
||||
|
||||
def check_quoted_status(self, tweet):
|
||||
""" Helper for get_quoted_tweet. Get a quoted status inside a tweet and create a special tweet with all info available.
|
||||
tweet dict: A tweet dictionary.
|
||||
Returns a quoted tweet or the original tweet if is not a quote"""
|
||||
status = tweets.is_long(tweet)
|
||||
if status != False and config.app["app-settings"]["handle_longtweets"]:
|
||||
quoted_tweet = self.get_quoted_tweet(tweet)
|
||||
@@ -510,6 +350,7 @@ class Session(object):
|
||||
return tweet
|
||||
|
||||
def get_quoted_tweet(self, tweet):
|
||||
""" Process a tweet and extract all information related to the quote."""
|
||||
quoted_tweet = tweet
|
||||
if tweet.has_key("full_text"):
|
||||
value = "full_text"
|
||||
@@ -539,6 +380,9 @@ class Session(object):
|
||||
return compose.compose_quoted_tweet(quoted_tweet, original_tweet)
|
||||
|
||||
def check_long_tweet(self, tweet):
|
||||
""" Process a tweet and add extra info if it's a long tweet made with Twyshort.
|
||||
tweet dict: a tweet object.
|
||||
returns a tweet with a new argument message, or original tweet if it's not a long tweet."""
|
||||
long = twishort.is_long(tweet)
|
||||
if long != False and config.app["app-settings"]["handle_longtweets"]:
|
||||
message = twishort.get_full_text(long)
|
||||
@@ -562,22 +406,28 @@ class Session(object):
|
||||
return tweet
|
||||
|
||||
def get_user(self, id):
|
||||
""" Returns an user object associated with an ID.
|
||||
id str: User identifier, provided by Twitter.
|
||||
returns an user dict."""
|
||||
if self.db.has_key("users") == False or self.db["users"].has_key(id) == False:
|
||||
user = self.twitter.twitter.show_user(id=id)
|
||||
user = self.twitter.show_user(id=id)
|
||||
self.db["users"][user["id_str"]] = user
|
||||
return user
|
||||
else:
|
||||
return self.db["users"][id]
|
||||
|
||||
def get_user_by_screen_name(self, screen_name):
|
||||
""" Returns an user identifier associated with a screen_name.
|
||||
screen_name str: User name, such as tw_blue2, provided by Twitter.
|
||||
returns an user ID."""
|
||||
if self.db.has_key("users") == False:
|
||||
user = utils.if_user_exists(self.twitter.twitter, screen_name)
|
||||
user = utils.if_user_exists(self.twitter, screen_name)
|
||||
self.db["users"][user["id_str"]] = user
|
||||
return user["id_str"]
|
||||
else:
|
||||
for i in self.db["users"].keys():
|
||||
if self.db["users"][i]["screen_name"] == screen_name:
|
||||
return self.db["users"][i]["id_str"]
|
||||
user = utils.if_user_exists(self.twitter.twitter, screen_name)
|
||||
user = utils.if_user_exists(self.twitter, screen_name)
|
||||
self.db["users"][user["id_str"]] = user
|
||||
return user["id_str"]
|
17
src/sessions/twitter/wxUI.py
Normal file
17
src/sessions/twitter/wxUI.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import wx
|
||||
|
||||
class authorisationDialog(wx.Dialog):
|
||||
def __init__(self):
|
||||
super(authorisationDialog, self).__init__(parent=None, title=_(u"Authorising account..."))
|
||||
panel = wx.Panel(self)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
static = wx.StaticText(panel, wx.NewId(), _(u"Enter your PIN code here"))
|
||||
self.text = wx.TextCtrl(panel, -1)
|
||||
self.ok = wx.Button(panel, wx.ID_OK)
|
||||
self.cancel = wx.Button(panel, wx.ID_CANCEL)
|
||||
sizer.Add(self.text, 0, wx.ALL, 5)
|
||||
sizer.Add(self.cancel, 0, wx.ALL, 5)
|
||||
panel.SetSizer(sizer)
|
||||
min = sizer.CalcMin()
|
||||
self.SetClientSize(min)
|
@@ -112,7 +112,7 @@ data_files = get_data(),
|
||||
options = {
|
||||
'py2exe': {
|
||||
'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"],
|
||||
'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.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
import buffers, utils, compose, twitter
|
@@ -1,32 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import BaseHTTPServer
|
||||
import application
|
||||
from urlparse import urlparse, parse_qs
|
||||
from pubsub import pub
|
||||
|
||||
logged = False
|
||||
verifier = None
|
||||
|
||||
class handler(BaseHTTPServer.BaseHTTPRequestHandler, object):
|
||||
|
||||
def do_GET(self):
|
||||
global logged
|
||||
self.send_response(200)
|
||||
self.send_header("Content-type", "text/html")
|
||||
self.end_headers()
|
||||
logged = True
|
||||
params = parse_qs(urlparse(self.path).query)
|
||||
global verifier
|
||||
verifier = params.get('oauth_verifier', [None])[0]
|
||||
self.wfile.write(u"You have successfully logged into Twitter with {0}. You can close this window now.".format(application.name))
|
||||
pub.sendMessage("authorisation-accepted")
|
||||
pub.unsubscribe(self.cancelled, "authorisation-cancelled")
|
||||
self.finish()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
pub.subscribe(self.cancelled, "authorisation-cancelled")
|
||||
super(handler, self).__init__(*args, **kwargs)
|
||||
|
||||
def cancelled(self):
|
||||
pub.unsubscribe(self.cancelled, "authorisation-cancelled")
|
||||
self.finish()
|
@@ -1 +0,0 @@
|
||||
import stream, indibidual
|
@@ -1,77 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import config
|
||||
from requests.auth import HTTPProxyAuth
|
||||
from twitter import compose, utils
|
||||
from twython import TwythonStreamer
|
||||
from pubsub import pub
|
||||
import logging as original_logger
|
||||
log = original_logger.getLogger("TimelinesStream")
|
||||
|
||||
class timelinesStreamer(TwythonStreamer):
|
||||
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, session=None):
|
||||
self.session = session
|
||||
super(timelinesStreamer, self).__init__(app_key, app_secret, oauth_token, oauth_token_secret, timeout=60, retry_count=None, retry_in=180, handlers=None, chunk_size=1)
|
||||
self.lists = self.session.lists
|
||||
|
||||
def on_error(self, status_code, data):
|
||||
log.error("error in stream: %s: %s" % (status_code, data))
|
||||
# pub.sendMessage("stream-error", session=self.session.session_id)
|
||||
|
||||
def on_timeout(self, *args, **kwargs):
|
||||
log.error("Twitter timeout Error")
|
||||
# pub.sendMessage("stream-error", session=self.session.session_id)
|
||||
|
||||
def check_tls(self, data):
|
||||
for i in self.session.settings["other_buffers"]["timelines"]:
|
||||
if data["user"]["id_str"] == i:
|
||||
if utils.find_item(data["id"], self.session.db["%s-timeline" % (i,)]) != None:
|
||||
log.error("duplicated tweet. Ignoring it...")
|
||||
return
|
||||
# try:
|
||||
if utils.is_allowed(data, self.session.settings, "%s-timeline" % (i,)):
|
||||
data_ = self.session.check_quoted_status(data)
|
||||
data_ = self.session.check_long_tweet(data_)
|
||||
data = data_
|
||||
# except ValueError:
|
||||
# pass
|
||||
if self.session.settings["general"]["reverse_timelines"] == False: self.session.db["%s-timeline" % (i,)].append(data)
|
||||
else: self.session.db["%s-timeline" % (i,)].insert(0, data)
|
||||
pub.sendMessage("item-in-timeline", data= data, user= self.session.db["user_name"], who= i)
|
||||
return
|
||||
for i in self.session.lists:
|
||||
try:
|
||||
i.users.index(data["user"]["id"])
|
||||
usr = data["in_reply_to_user_id"]
|
||||
if (usr != None and usr in self.friends) or data.has_key("retweeted_status"):
|
||||
data = self.session.check_quoted_status(data)
|
||||
data = self.session.check_long_tweet(data)
|
||||
if self.session.settings["general"]["reverse_timelines"] == False: self.session.db["%s" % (i.name,)].append(data)
|
||||
else: self.session.db["%s" % (i.name,)].insert(0, data)
|
||||
pub.sendMessage("item-in-list", data=data, user=self.session.db["user_name"], where=i.name)
|
||||
elif usr == None:
|
||||
data = self.session.check_quoted_status(data)
|
||||
data = self.session.check_long_tweet(data)
|
||||
if self.session.settings["general"]["reverse_timelines"] == False: self.session.db["%s" % (i.name,)].append(data)
|
||||
else: self.session.db["%s" % (i.name,)].insert(0, data)
|
||||
pub.sendMessage("item-in-list", data=data, user=self.session.db["user_name"], where=i.name)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
def set_friends(self, friends):
|
||||
self.friends = friends
|
||||
|
||||
def on_success(self, data):
|
||||
if "text" in data:
|
||||
if data.has_key("extended_tweet"):
|
||||
data["full_text"] = data["extended_tweet"]["full_text"]
|
||||
if data.has_key("retweeted_status"):
|
||||
if data["retweeted_status"].has_key("extended_tweet"):
|
||||
data["retweeted_status"]["full_text"] = data["retweeted_status"]["extended_tweet"]["full_text"]
|
||||
data["retweeted_status"]["entities"] = data["retweeted_status"]["extended_tweet"]["entities"]
|
||||
data["full_text"] = data["text"]
|
||||
if data.has_key("quoted_status"):
|
||||
if data["quoted_status"].has_key("extended_tweet"):
|
||||
data["quoted_status"]["full_text"] = data["quoted_status"]["extended_tweet"]["full_text"]
|
||||
data["quoted_status"]["entities"] = data["quoted_status"]["extended_tweet"]["entities"]
|
||||
# data["full_text"] = data["text"]
|
||||
self.check_tls(data)
|
@@ -1,193 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import config
|
||||
from requests.auth import HTTPProxyAuth
|
||||
from twitter import utils
|
||||
from twython import TwythonStreamer
|
||||
from pubsub import pub
|
||||
import logging as original_logger
|
||||
log = original_logger.getLogger("MainStream")
|
||||
|
||||
class streamer(TwythonStreamer):
|
||||
def __init__(self, app_key, app_secret, oauth_token, oauth_token_secret, sessionObject, *a, **kw):
|
||||
super(streamer, self).__init__(app_key, app_secret, oauth_token, oauth_token_secret, *a, **kw)
|
||||
self.session = sessionObject
|
||||
self.muted_users = self.session.db["muted_users"]
|
||||
# self.blocked_users = []
|
||||
|
||||
def on_timeout(self, *args, **kwargs):
|
||||
log.error("Twitter timeout Error")
|
||||
# pub.sendMessage("stream-error", session=self.session.session_id)
|
||||
|
||||
def on_error(self, status_code, data):
|
||||
log.error("Error %s: %s" % (status_code, data))
|
||||
# pub.sendMessage("stream-error", session=self.session.session_id)
|
||||
|
||||
def get_user(self):
|
||||
return self.session.db["user_name"]
|
||||
|
||||
def put_data(self, place, data):
|
||||
if self.session.db.has_key(place):
|
||||
if utils.find_item(data["id"], self.session.db[place]) != None:
|
||||
log.error("duplicated tweet. Ignoring it...")
|
||||
return False
|
||||
# try:
|
||||
if utils.is_allowed(data, self.session.settings, place):
|
||||
data_ = self.session.check_quoted_status(data)
|
||||
data_ = self.session.check_long_tweet(data_)
|
||||
data = data_
|
||||
# except:
|
||||
# pass
|
||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||
self.session.db[place].append(data)
|
||||
else:
|
||||
self.session.db[place].insert(0, data)
|
||||
utils.is_audio(data)
|
||||
return True
|
||||
return False
|
||||
|
||||
def block_user(self, data):
|
||||
id = data["target"]["id"]
|
||||
if id in self.friends:
|
||||
self.friends.remove(id)
|
||||
if "blocks" in self.session.settings["general"]["buffer_order"]:
|
||||
self.session.db["blocked"]["items"].append(data["target"])
|
||||
pub.sendMessage("blocked-user", data=data["target"], user=self.get_user())
|
||||
|
||||
def unblock(self, data):
|
||||
if "blocks" in self.session.settings["general"]["buffer_order"] == True:
|
||||
item = utils.find_item(data["target"]["id"], self.session.db["blocked"]["items"])
|
||||
self.session.db["blocked"]["items"].pop(item)
|
||||
pub.sendMessage("unblocked-user", item=item, user=self.get_user())
|
||||
|
||||
def check_send(self, data):
|
||||
if self.session.db["user_name"] == data["user"]["screen_name"]:
|
||||
d = self.put_data("sent_tweets", data)
|
||||
if d != False:
|
||||
pub.sendMessage("sent-tweet", data=data, user=self.get_user())
|
||||
|
||||
def check_favs(self, data):
|
||||
if data["source"]["screen_name"] == self.session.db["user_name"]:
|
||||
d = self.put_data("favourites", data["target_object"])
|
||||
if d != False:
|
||||
pub.sendMessage("favourite", data=data["target_object"], user=self.get_user())
|
||||
|
||||
def check_mentions(self, data):
|
||||
if "@%s" % (self.session.db["user_name"]) in data["text"]:
|
||||
d = self.put_data("mentions", data)
|
||||
if d != False:
|
||||
pub.sendMessage("mention", data=data, user=self.get_user())
|
||||
|
||||
def set_quoted_tweet(self, data):
|
||||
if data["source"]["screen_name"] != self.session.db["user_name"]:
|
||||
d = self.put_data("mentions", data["target_object"])
|
||||
if d != False:
|
||||
pub.sendMessage("mention", data=data["target_object"], user=self.get_user())
|
||||
|
||||
def process_dm(self, data):
|
||||
return
|
||||
if self.session.db["user_name"] != data["direct_message"]["sender"]["screen_name"]:
|
||||
# d = self.put_data("sent_direct_messages", data["direct_message"])
|
||||
# if d != False:
|
||||
# pub.sendMessage("sent-dm", data=data["direct_message"], user=self.get_user())
|
||||
# else:
|
||||
d = self.put_data("direct_messages", data["direct_message"])
|
||||
if d != False:
|
||||
pub.sendMessage("direct-message", data=data["direct_message"], user=self.get_user())
|
||||
|
||||
def check_follower(self, data):
|
||||
if data["target"]["screen_name"] == self.session.db["user_name"]:
|
||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||
self.session.db["followers"]["items"].append(data["source"])
|
||||
else:
|
||||
self.session.db["followers"]["items"].insert(0, data["source"])
|
||||
pub.sendMessage("follower", data=data["source"], user = self.get_user())
|
||||
else:
|
||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||
self.session.db["friends"]["items"].append(data["target"])
|
||||
else:
|
||||
self.session.db["friends"]["items"].insert(0, data["target"])
|
||||
pub.sendMessage("friend", data=data["target"], user=self.get_user())
|
||||
|
||||
###
|
||||
def remove_fav(self, data):
|
||||
if self.session.db["user_name"] == data["source"]["screen_name"]:
|
||||
item = utils.find_item(data["target_object"]["id"], self.session.db["favourites"])
|
||||
self.session.db["favourites"].pop(item)
|
||||
pub.sendMessage("unfavourite", item=item, user=self.get_user())
|
||||
|
||||
def remove_friend(self, data):
|
||||
if "friends" in self.session.settings["general"]["buffer_order"]:
|
||||
item = utils.find_item(data["target"]["id"], self.session.db["friends"]["items"])
|
||||
if item > 0:
|
||||
self.friends.pop(item)
|
||||
pub.sendMessage("unfollowing", item=item, user=self.get_user())
|
||||
|
||||
def on_success(self, data):
|
||||
try:
|
||||
# if "delete" in data:
|
||||
# pub.sendMessage("tweet-deleted", data=data)
|
||||
if "direct_message" in data:
|
||||
self.process_dm(data)
|
||||
elif "friends" in data:
|
||||
self.friends = data["friends"]
|
||||
pub.sendMessage("friends-receibed")
|
||||
elif "text" in data:
|
||||
if data.has_key("extended_tweet"):
|
||||
data["full_text"] = data["extended_tweet"]["full_text"]
|
||||
data["entities"] = data["extended_tweet"]["entities"]
|
||||
if data.has_key("retweeted_status"):
|
||||
if data["retweeted_status"].has_key("extended_tweet"):
|
||||
data["retweeted_status"]["full_text"] = data["retweeted_status"]["extended_tweet"]["full_text"]
|
||||
data["retweeted_status"]["entities"] = data["retweeted_status"]["extended_tweet"]["entities"]
|
||||
data["full_text"] = data["text"]
|
||||
if data.has_key("quoted_status"):
|
||||
if data["quoted_status"].has_key("extended_tweet"):
|
||||
data["quoted_status"]["full_text"] = data["quoted_status"]["extended_tweet"]["full_text"]
|
||||
data["quoted_status"]["entities"] = data["quoted_status"]["extended_tweet"]["entities"]
|
||||
# data["full_text"] = data["quoted_status"]["full_text"]
|
||||
if data["user"]["id"] in self.muted_users: return
|
||||
self.check_mentions(data)
|
||||
self.check_send(data)
|
||||
if data["user"]["id"] in self.friends or data["user"]["screen_name"] == self.session.db["user_name"]:
|
||||
d = self.put_data("home_timeline", data)
|
||||
if d != False:
|
||||
pub.sendMessage("item-in-home", data=data, user=self.get_user())
|
||||
elif data.has_key("event"):
|
||||
if "favorite" == data["event"] and "favorites" in self.session.settings["general"]["buffer_order"]:
|
||||
self.check_favs(data)
|
||||
elif "unfavorite" == data["event"] and "favorites" in self.session.settings["general"]["buffer_order"]:
|
||||
self.remove_fav(data)
|
||||
elif "follow" == data["event"] and "followers" in self.session.settings["general"]["buffer_order"]:
|
||||
self.check_follower(data)
|
||||
elif "unfollow" == data["event"] and "friends" in self.session.settings["general"]["buffer_order"]:
|
||||
self.remove_friend(data)
|
||||
elif "block" == data["event"]:
|
||||
self.block_user(data)
|
||||
elif "unblock" == data["event"]:
|
||||
self.unblock(data)
|
||||
elif "list_created" == data["event"]:
|
||||
item = utils.find_item(data["target_object"]["id"], self.session.db["lists"])
|
||||
if item != None: self.session.db["lists"].append(data["target_object"])
|
||||
elif "list_destroyed" == data["event"]:
|
||||
item = utils.find_item(data["target_object"]["id"], self.session.db["lists"])
|
||||
if item != None: self.session.db["lists"].pop(item)
|
||||
self.parent.remove_list(data["target_object"]["id"])
|
||||
elif "list_member_added" == data["event"] and data["source"]["screen_name"] == self.get_user():
|
||||
pub.sendMessage("new-list-member-added", **{"id":str(data["target"]["id"]), "list":data["target_object"], "user":self.get_user()})
|
||||
elif "list_member_added" == data["event"] and data["target"]["screen_name"] == self.get_user():
|
||||
self.session.db["lists"].append(data["target_object"])
|
||||
elif "list_member_removed" == data["event"] and data["source"]["screen_name"] == self.get_user():
|
||||
pub.sendMessage("list-member-deleted", **{"id":str(data["target"]["id"]), "list":data["target_object"], "user":self.get_user()})
|
||||
elif "list_member_removed" == data["event"] and data["target"] == self.get_user():
|
||||
id = data["target_object"]["id"]
|
||||
list = utils.find_item(id, self.session.db["lists"])
|
||||
if list != None: self.session.db["lists"].pop(list)
|
||||
pub.sendMessage("list-deleted", **{"item":list, "user":self.get_user()})
|
||||
elif "quoted_tweet" == data["event"]:
|
||||
self.set_quoted_tweet(data)
|
||||
|
||||
if "events" in self.session.settings["general"]["buffer_order"]:
|
||||
pub.sendMessage("event", data= data, user= self.get_user())
|
||||
# self.sound.play("new_event.ogg")
|
||||
except KeyboardInterrupt:
|
||||
pass
|
@@ -1,31 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import config
|
||||
import random
|
||||
import webbrowser
|
||||
from twython import Twython, TwythonError
|
||||
from keys import keyring
|
||||
from requests import certs
|
||||
import logging
|
||||
log = logging.getLogger("sessionTwitter")
|
||||
|
||||
class twitter(object):
|
||||
|
||||
def login(self, user_key, user_secret, verify_credentials):
|
||||
self.twitter = Twython(keyring.get("api_key"), keyring.get("api_secret"), user_key, user_secret)
|
||||
if verify_credentials == True:
|
||||
self.credentials = self.twitter.verify_credentials()
|
||||
|
||||
def authorise(self):
|
||||
twitter = Twython(keyring.get("api_key"), keyring.get("api_secret"))
|
||||
self.auth = twitter.get_authentication_tokens(callback_url="oob")
|
||||
webbrowser.open_new_tab(self.auth['auth_url'])
|
||||
|
||||
def verify_authorisation(self, settings, pincode):
|
||||
self.twitter = Twython(keyring.get("api_key"), keyring.get("api_secret"), self.auth['oauth_token'], self.auth['oauth_token_secret'])
|
||||
final = self.twitter.get_authorized_tokens(pincode)
|
||||
self.save_configuration(settings, final["oauth_token"], final["oauth_token_secret"])
|
||||
|
||||
def save_configuration(self, settings, user_key, user_secret):
|
||||
settings["twitter"]["user_key"] = user_key
|
||||
settings["twitter"]["user_secret"] = user_secret
|
||||
settings.write()
|
@@ -102,14 +102,6 @@ class generalAccount(wx.Panel, baseDialog.BaseWXDialog):
|
||||
sizer.Add(self.au, 0, wx.ALL, 5)
|
||||
self.relative_time = wx.CheckBox(self, wx.ID_ANY, _(U"Relative timestamps"))
|
||||
sizer.Add(self.relative_time, 0, wx.ALL, 5)
|
||||
if application.streaming_lives():
|
||||
apiCallsBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
apiCallsBox.Add(wx.StaticText(self, -1, _(u"API calls (One API call = 200 tweets, two API calls = 400 tweets, etc):")), 0, wx.ALL, 5)
|
||||
self.apiCalls = wx.SpinCtrl(self, wx.ID_ANY)
|
||||
self.apiCalls.SetRange(1, 10)
|
||||
self.apiCalls.SetSize(self.apiCalls.GetBestSize())
|
||||
apiCallsBox.Add(self.apiCalls, 0, wx.ALL, 5)
|
||||
sizer.Add(apiCallsBox, 0, wx.ALL, 5)
|
||||
tweetsPerCallBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
tweetsPerCallBox.Add(wx.StaticText(self, -1, _(u"Items on each API call")), 0, wx.ALL, 5)
|
||||
self.itemsPerApiCall = wx.SpinCtrl(self, wx.ID_ANY)
|
||||
|
@@ -74,6 +74,7 @@ class mainFrame(wx.Frame):
|
||||
self.check_for_updates = help.Append(wx.ID_ANY, _(u"&Check for updates"))
|
||||
self.reportError = help.Append(wx.ID_ANY, _(u"&Report an error"))
|
||||
self.visit_website = help.Append(-1, _(u"{0}'s &website").format(application.name,))
|
||||
self.get_soundpacks = help.Append(-1, _(u"Get soundpacks for TWBlue"))
|
||||
self.about = help.Append(-1, _(u"About &{0}").format(application.name,))
|
||||
|
||||
# Add all to the menu Bar
|
||||
|
Submodule windows-dependencies updated: 814ea75d5d...c80247f5e1
Reference in New Issue
Block a user