Merge branch 'next-gen' into fr-04062020

This commit is contained in:
Oreonan 2021-05-14 21:24:46 +02:00 committed by GitHub
commit 40040d1b17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 2500 additions and 6146 deletions

View File

@ -24,35 +24,37 @@ This document describes how to run tw blue from source and how to build a binary
### Required dependencies.
Although most dependencies can be found in the windows-dependencies directory, we provide links to their official websites. If you are cloning with git, don't forget to initialize and update the submodules to get the windows-dependencies folder. You can use these two commands to perform this task from git bash:
```
git submodule init
git submodule update
```
#### Dependencies packaged in windows installers
* [Python,](http://python.org) version 3.7.7
If you want to build both x86 and x64 binaries, you can install python x86 to C:\python37 and python x64 to C:\python37x64, for example.
* [Python,](https://python.org) version 3.8.7
If you want to build both x86 and x64 binaries, you can install python x86 to C:\python38 and python x64 to C:\python38x64, for example.
#### Dependencies that must be installed using pip
Python installs a tool called Pip that allows to install packages in a simple way. You can find it in the python scripts directory. To install packages using Pip, you have to navigate to the scripts directory using a command prompt, for example:
cd C:\python37x64\scripts
`cd C:\python37x64\scripts`
You can also add the scripts folder to your path environment variable or choose the corresponding option when installing Python.
Note: pip and setuptools are included in the Python installer since version 2.7.9.
Pip is able to install packages listed in a special text file, called the requirements file. To install all remaining dependencies, perform the following command:
pip install -r requirements.txt
`pip install -r requirements.txt`
Note that if you perform the command from the path where Pip is located, you need to specify the path to your Tw Blue root folder where the requirements file is located, for example:
pip install -r D:\repos\TwBlue\requirements.txt
`pip install -r D:\repos\TwBlue\requirements.txt`
Pip will automatically get the additional libraries that the listed packages need to work properly.
If you need to update your dependencies, perform the following command:
pip install --upgrade -r requirements.txt
`pip install --upgrade -r requirements.txt`
#### Other dependencies
@ -61,7 +63,7 @@ These dependencies are located in the windows-dependencies directory. You don't
* Bootstrap 1.2.1: included in dependencies directory.
This dependency has been built using pure basic 4.61. Its source can be found at http://hg.q-continuum.net/updater
* [oggenc2.exe,](http://www.rarewares.org/ogg-oggenc.php) version 2.87
* Microsoft Visual c++ 2017 redistributable dlls.
* Microsoft Visual c++ 2019 redistributable dlls.
* VLC plugins and DLL libraries.
#### Dependencies required to build the installer
@ -84,7 +86,7 @@ In order to add the support for spell checking in more languages than english yo
Now that you have installed all these packages, you can run TW Blue from source using a command prompt. Navigate to the repo's `src` directory, and type the following command:
python main.py
`python main.py`
If necessary, change the first part of the command to reflect the location of your python executable. You can run TW Blue using python x86 and x64.
@ -92,8 +94,8 @@ Now that you have installed all these packages, you can run TW Blue from source
To generate the documentation in html format, navigate to the doc folder inside this repo. After that, run these commands:
python document_importer.py
python generator.py
`python document_importer.py`
`python generator.py`
The documentation will be generated, placing each language in a separate folder in the doc directory. Move these folders (for example `de`, `en`, `es`, `fr`, `it`, ...) to `src/documentation`, creating the directory if necessary.
Also, copy the `license.txt` file located in the root of the repo to the documentation folder.
@ -104,7 +106,7 @@ A binary version doesn't need python and the other dependencies to run, it's the
To build it, run the following command from the src folder:
python setup.py build
`python setup.py build`
You will find the binaries in the dist directory.

View File

@ -10,8 +10,8 @@ environment:
matrix:
# List of python versions we want to work with.
- PYTHON: "C:\\Python37"
PYTHON_VERSION: "3.7.x" # currently 2.7.9
- PYTHON: "C:\\Python38"
PYTHON_VERSION: "3.8.x" # currently 2.7.9
PYTHON_ARCH: "32"
# perhaps we may enable this one in future?

View File

@ -40,3 +40,4 @@ Christian Leo Mameli
Natalia Hedlund (Наталья Хедлунд)
Valeria (Валерия)
Oreonan
Artem Plaksin (maniyax)

View File

@ -2,12 +2,24 @@
## changes in this version
* Fixed error when displaying an URL at the end of a line, when the tweet or direct message contained multiple lines. Now the URL should be displayed correctly. ([#305,](https://github.com/manuelcortez/TWBlue/issues/305))
* TWBlue has been migrated completely to Python 3 (currently, the software builds with Python 3.7).
* Changed the label in the direct message's text control so it will indicate that the user needs to write the text there, without referring to any username in particular. ([#366,](https://github.com/manuelcortez/TWBlue/issues/366))
* TWBlue will take Shift+F10 again as the contextual menu key in the list of items in a buffer. This stopped working after we have migrated to WX 4.1. ([#353,](https://github.com/manuelcortez/TWBlue/issues/353))
* TWBlue should render correctly retweets of quoted tweets. ([#365,](https://github.com/manuelcortez/TWBlue/issues/365))
* Fixed an error that was causing TWBlue to be unable to output to screen readers at times. ([#369,](https://github.com/manuelcortez/TWBlue/issues/369))
* Fixed autocomplete users feature. ([#367,](https://github.com/manuelcortez/TWBlue/issues/367))
* Fixed error when displaying an URL at the end of a line, when the tweet or direct message contained multiple lines. Now the URL should be displayed correctly. ([#305,](https://github.com/manuelcortez/TWBlue/issues/305) [#272,](https://github.com/manuelcortez/TWBlue/issues/272))
* TWBlue has been migrated completely to Python 3 (currently, the software builds with Python 3.8).
* TWBlue should be restarted gracefully. Before, the application was alerting users of not being closed properly every time the application restarted by itself.
* If TWBlue attemps to load an account with invalid tokens (this happens when reactivating a previously deactivated account, or when access to the ap is revoqued), TWBlue will inform the user about this error and will skip the account. Before, the app was unable to start due to a critical error. ([#328,](https://github.com/manuelcortez/TWBlue/issues/328))
* When sending a direct message, the title of the window will change appropiately when the recipient is edited. ([#276,](https://github.com/manuelcortez/TWBlue/issues/276))
* URL'S in user profiles are expanded automatically. ([#275,](https://github.com/manuelcortez/TWBlue/issues/275))
* TWBlue now uses [Tweepy,](https://github.com/tweepy/tweepy) to connect with Twitter. We have adopted this change in order to support Twitter'S API V 2 in the very near future. ([#333,](https://github.com/manuelcortez/TWBlue/issues/337) [#347](https://github.com/manuelcortez/TWBlue/pull/347))
* TWBlue can upload images in Tweets and replies again. ([#240,](https://github.com/manuelcortez/TWBlue/issues/240))
* Fixed the way we use to count characters in Twitter. The new methods in TWBlue take into account special characters and URLS as documented in Twitter. ([#199,](https://github.com/manuelcortez/TWBlue/issues/199) [#315](https://github.com/manuelcortez/TWBlue/issues/315))
* Proxy support now works as expected.
* Changed translation service from yandex.translate to Google Translator. ([#355,](https://github.com/manuelcortez/TWBlue/issues/355))
* Improved method to load direct messages in the buffers. Now it should be faster due to less calls to Twitter API performed from the client.
* And more. ([#352,](https://github.com/manuelcortez/TWBlue/issues/352))
## Changes in version 0.95

View File

@ -1,4 +1,5 @@
wxpython==4.0.3
wxpython
wheel
six
configobj
markdown
@ -15,8 +16,10 @@ futures
winpaths
PySocks
win_inet_pton
yandex.translate
idna
# Install the latest RC of this lib
# see https://github.com/ssut/py-googletrans/issues/234
googletrans==4.0.0-rc1
idna<3,>=2.5
chardet
urllib3
youtube-dl
@ -25,8 +28,10 @@ pypiwin32
certifi
backports.functools_lru_cache
cx_freeze
git+https://github.com/manuelcortez/twython
git+https://github.com/manuelcortez/libloader
git+https://github.com/manuelcortez/platform_utils
git+https://github.com/manuelcortez/accessible_output2
git+https://github.com/jmdaweb/sound_lib
tweepy
twitter-text-parser
pyenchant
git+https://github.com/accessibleapps/libloader
git+https://github.com/accessibleapps/platform_utils
git+https://github.com/accessibleapps/accessible_output2
git+https://github.com/accessibleapps/sound_lib

View File

@ -24,8 +24,8 @@ mention_all = boolean(default=False)
no_streaming = boolean(default=False)
[proxy]
type = string(default="Direct connection")
type = integer(default=0)
server = string(default="")
port = string(default="")
port = integer(default=8080)
user = string(default="")
password = string(default="")

View File

@ -9,12 +9,12 @@ if snapshot == False:
update_url = 'https://twblue.es/updates/stable.php'
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/stable.json'
else:
version = "3"
version = "5"
update_url = 'https://twblue.es/updates/snapshot.php'
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/snapshots.json'
authors = ["Manuel Cortéz", "José Manuel Delicado"]
authorEmail = "manuel@manuelcortez.net"
copyright = "Copyright (C) 2013-2018, Manuel cortéz."
copyright = "Copyright (C) 2013-2021, Manuel cortéz."
description = name+" is an app designed to use Twitter simply and efficiently while using minimal system resources. This app provides access to most Twitter features."
translators = ["Manuel Cortéz (English)", "Mohammed Al Shara, Hatoun Felemban (Arabic)", "Francisco Torres (Catalan)", "Manuel cortéz (Spanish)", "Sukil Etxenike Arizaleta (Basque)", "Jani Kinnunen (finnish)", "Oreonan (Français)", "Juan Buño (Galician)", "Steffen Schultz (German)", "Zvonimir Stanečić (Croatian)", "Robert Osztolykan (Hungarian)", "Christian Leo Mameli (Italian)", "Riku (Japanese)", "Paweł Masarczyk (Polish)", "Odenilton Júnior Santos (Portuguese)", "Florian Ionașcu, Nicușor Untilă (Romanian)", "Natalia Hedlund, Valeria Kuznetsova (Russian)", "Aleksandar Đurić (Serbian)", "Burak Yüksek (Turkish)"]
url = u"https://twblue.es"

View File

@ -9,7 +9,7 @@ log = logging.getLogger("config")
MAINFILE = "twblue.conf"
MAINSPEC = "app-configuration.defaults"
proxyTypes=[u"http", u"https", u"socks4", u"socks5"]
proxyTypes = ["system", "http", "socks4", "socks4a", "socks5", "socks5h"]
app = None
keymap=None
changed_keymap = False

View File

@ -59,11 +59,17 @@ class buffer(object):
elif ev.GetKeyCode() == wx.WXK_F6: event = "volume_up"
elif ev.GetKeyCode() == wx.WXK_DELETE and ev.ShiftDown(): event = "clear_list"
elif ev.GetKeyCode() == wx.WXK_DELETE: event = "destroy_status"
# Raise a Special event when pressed Shift+F10 because Wx==4.1.x does not seems to trigger this by itself.
# See https://github.com/manuelcortez/TWBlue/issues/353
elif ev.GetKeyCode() == wx.WXK_F10 and ev.ShiftDown(): event = "show_menu"
else:
event = None
ev.Skip()
if event != None:
try:
### ToDo: Remove after WX fixes issue #353 in the widgets.
if event == "show_menu":
return self.show_menu(widgetUtils.MENU, pos=self.buffer.list.list.GetPosition())
getattr(self, event)()
except AttributeError:
pass

View File

@ -1,7 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from builtins import str
from builtins import range
import time
import platform
if platform.system() == "Windows":
@ -24,7 +21,8 @@ from audio_services import youtube_utils
from controller.buffers import baseBuffers
from sessions.twitter import compose, utils
from mysc.thread_utils import call_threaded
from twython import TwythonError
from tweepy.error import TweepError
from tweepy.cursor import Cursor
from pubsub import pub
from sessions.twitter.long_tweets import twishort, tweets
@ -86,6 +84,7 @@ class baseBufferController(baseBuffers.buffer):
return _(u"Unknown buffer")
def post_status(self, *args, **kwargs):
item = None
title = _(u"Tweet")
caption = _(u"Write the tweet here")
tweet = messages.tweet(self.session, title, caption, "")
@ -101,8 +100,8 @@ class baseBufferController(baseBuffers.buffer):
text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text, 1)
if not hasattr(tweet, "attachments") or len(tweet.attachments) == 0:
item = self.session.api_call(call_name="update_status", status=text, _sound="tweet_send.ogg", tweet_mode="extended")
# else:
# call_threaded(self.post_with_media, text=text, attachments=tweet.attachments, _sound="tweet_send.ogg")
else:
call_threaded(self.post_with_media, text=text, attachments=tweet.attachments)
if item != None:
pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
if hasattr(tweet.message, "destroy"): tweet.message.destroy()
@ -111,11 +110,12 @@ class baseBufferController(baseBuffers.buffer):
def post_with_media(self, text, attachments):
media_ids = []
for i in attachments:
photo = open(i["file"], "rb")
img = self.session.twitter.upload_media(media=photo)
self.session.twitter.create_metadata(media_id=img["media_id"], alt_text=dict(text=i["description"]))
media_ids.append(img["media_id"])
self.session.twitter.update_status(status=text, media_ids=media_ids)
img = self.session.twitter.media_upload(i["file"])
self.session.twitter.create_media_metadata(media_id=img.media_id, alt_text=i["description"])
media_ids.append(img.media_id)
item = self.session.twitter.update_status(status=text, media_ids=media_ids)
if item != None:
pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
def get_formatted_message(self):
if self.type == "dm" or self.name == "direct_messages":
@ -129,31 +129,25 @@ class baseBufferController(baseBuffers.buffer):
def get_full_tweet(self):
tweet = self.get_right_tweet()
tweetsList = []
tweet_id = tweet["id"]
tweet_id = tweet.id
message = None
if "message" in tweet:
message = tweet["message"]
if hasattr(tweet, "message"):
message = tweet.message
try:
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"])
except IndexError: pass
except TwythonError as e:
tweet = self.session.twitter.get_status(id=tweet_id, include_ext_alt_text=True, tweet_mode="extended")
tweet.full_text = utils.expand_urls(tweet.full_text, tweet.entities)
except TweepError as e:
utils.twitter_error(e)
return
if message != None:
tweet["message"] = message
tweet.message = message
l = tweets.is_long(tweet)
while l != False:
tweetsList.append(tweet)
try:
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"])
except IndexError: pass
except TwythonError as e:
tweet = self.session.twitter.get_status(id=l, include_ext_alt_text=True, tweet_mode="extended")
tweet.full_text = utils.expand_urls(tweet.full_text, tweet.entities)
except TweepError as e:
utils.twitter_error(e)
return
l = tweets.is_long(tweet)
@ -168,18 +162,41 @@ class baseBufferController(baseBuffers.buffer):
self.execution_time = current_time
log.debug("Starting stream for buffer %s, account %s and type %s" % (self.name, self.account, self.type))
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
if self.name == "direct_messages":
number_of_items = self.session.get_cursored_stream(self.name, self.function, *self.args, **self.kwargs)
else:
if self.name != "direct_messages":
val = self.session.call_paged(self.function, *self.args, **self.kwargs)
else:
# 50 results are allowed per API call, so let's assume max value can be 50.
# reference: https://developer.twitter.com/en/docs/twitter-api/v1/direct-messages/sending-and-receiving/api-reference/list-events
if self.session.settings["general"]["max_tweets_per_call"] > 50:
count = 50
else:
count = self.session.settings["general"]["max_tweets_per_call"]
# try to retrieve the cursor for the current buffer.
try:
val = getattr(self.session.twitter, self.function)(return_cursors=True, count=count, *self.args, **self.kwargs)
if type(val) == tuple:
val, cursor = val
if type(cursor) == tuple:
cursor = cursor[1]
self.session.db["cursors"][self.name] = cursor
results = [i for i in val]
val = results
val.reverse()
log.debug("Retrieved %d items from the cursored search on function %s." %(len(val), self.function))
user_ids = [item.message_create["sender_id"] for item in val]
self.session.save_users(user_ids)
except TweepError as e:
log.error("Error %s: %s" % (e.api_code, e.reason))
return
number_of_items = self.session.order_buffer(self.name, val)
log.debug("Number of items retrieved: %d" % (number_of_items,))
self.put_items_on_list(number_of_items)
if hasattr(self, "finished_timeline") and self.finished_timeline == False:
if "-timeline" in self.name:
self.username = val[0]["user"]["screen_name"]
self.username = val[0].user.screen_name
elif "-favorite" in self.name:
self.username = self.session.api_call("show_user", **self.kwargs)["screen_name"]
self.username = self.session.api_call("get_user", **self.kwargs).screen_name
self.finished_timeline = True
if number_of_items > 0 and self.name != "sent_tweets" and self.name != "sent_direct_messages" and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
self.session.sound.play(self.sound)
@ -202,17 +219,18 @@ class baseBufferController(baseBuffers.buffer):
def get_more_items(self):
elements = []
if self.session.settings["general"]["reverse_timelines"] == False:
last_id = self.session.db[self.name][0]["id"]
last_id = self.session.db[self.name][0].id
else:
last_id = self.session.db[self.name][-1]["id"]
last_id = self.session.db[self.name][-1].id
try:
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)
items = getattr(self.session.twitter, self.function)(max_id=last_id, count=self.session.settings["general"]["max_tweets_per_call"], *self.args, **self.kwargs)
except TweepError as e:
log.error("Error %s: %s" % (e.api_code, e.reason))
return
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:
if utils.is_allowed(i, self.session.settings, self.name) == True and utils.find_item(i.id, self.session.db[self.name]) == None:
i = self.session.check_quoted_status(i)
i = self.session.check_long_tweet(i)
elements.append(i)
@ -221,6 +239,7 @@ class baseBufferController(baseBuffers.buffer):
else:
self.session.db[self.name].append(i)
selection = self.buffer.list.get_selected()
log.debug("Retrieved %d items from cursored search in function %s." % (len(elements), self.function))
if self.session.settings["general"]["reverse_timelines"] == False:
for i in elements:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session)
@ -229,8 +248,6 @@ class baseBufferController(baseBuffers.buffer):
for i in items:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session)
self.buffer.list.insert_item(False, *tweet)
# self.buffer.list.select_item(selection+elements)
# else:
self.buffer.list.select_item(selection)
output.speak(_(u"%s items retrieved") % (str(len(elements))), True)
@ -270,16 +287,12 @@ class baseBufferController(baseBuffers.buffer):
def remove_tweet(self, id):
if type(self.session.db[self.name]) == dict: return
for i in range(0, len(self.session.db[self.name])):
if self.session.db[self.name][i]["id"] == id:
if self.session.db[self.name][i].id == id:
self.session.db[self.name].pop(i)
self.remove_item(i)
def put_items_on_list(self, number_of_items):
# Define the list we're going to use as cursored stuff are a bit different.
if self.name != "direct_messages" and self.name != "sent_direct_messages":
list_to_use = self.session.db[self.name]
else:
list_to_use = self.session.db[self.name]["items"]
if number_of_items == 0 and self.session.settings["general"]["persist_size"] == 0: return
log.debug("The list contains %d items " % (self.buffer.list.get_count(),))
log.debug("Putting %d items on the list" % (number_of_items,))
@ -382,8 +395,8 @@ class baseBufferController(baseBuffers.buffer):
self.show_menu(widgetUtils.MENU, pos=self.buffer.list.list.GetPosition())
def get_tweet(self):
if "retweeted_status" in self.session.db[self.name][self.buffer.list.get_selected()]:
tweet = self.session.db[self.name][self.buffer.list.get_selected()]["retweeted_status"]
if hasattr(self.session.db[self.name][self.buffer.list.get_selected()], "retweeted_status"):
tweet = self.session.db[self.name][self.buffer.list.get_selected()].retweeted_status
else:
tweet = self.session.db[self.name][self.buffer.list.get_selected()]
return tweet
@ -395,9 +408,9 @@ class baseBufferController(baseBuffers.buffer):
@_tweets_exist
def reply(self, *args, **kwargs):
tweet = self.get_right_tweet()
screen_name = tweet["user"]["screen_name"]
id = tweet["id"]
twishort_enabled = "twishort" in tweet
screen_name = tweet.user.screen_name
id = tweet.id
twishort_enabled = hasattr(tweet, "twishort")
users = utils.get_all_mentioned(tweet, self.session.db, field="screen_name")
ids = utils.get_all_mentioned(tweet, self.session.db, field="id_str")
# Build the window title
@ -432,7 +445,6 @@ class baseBufferController(baseBuffers.buffer):
else:
params["call_name"] = "update_status_with_media"
params["media"] = message.file
item = self.session.api_call(**params)
if item != None:
pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
@ -443,44 +455,33 @@ class baseBufferController(baseBuffers.buffer):
def send_message(self, *args, **kwargs):
tweet = self.get_right_tweet()
if self.type == "dm":
screen_name = self.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]
screen_name = self.session.get_user(tweet.message_create["sender_id"]).screen_name
users = [screen_name]
elif self.type == "people":
screen_name = tweet["screen_name"]
screen_name = tweet.screen_name
users = [screen_name]
else:
screen_name = tweet["user"]["screen_name"]
screen_name = tweet.user.screen_name
users = utils.get_all_users(tweet, self.session.db)
dm = messages.dm(self.session, _(u"Direct message to %s") % (screen_name,), _(u"New direct message"), users)
if dm.message.get_response() == widgetUtils.OK:
screen_name = dm.message.get("cb")
user = self.session.get_user_by_screen_name(screen_name)
event_data = {
'event': {
'type': 'message_create',
'message_create': {
'target': {
'recipient_id': user,
},
'message_data': {
'text': dm.message.get_text(),
}
}
}
}
val = self.session.api_call(call_name="send_direct_message", **event_data)
recipient_id = user
text = dm.message.get_text()
val = self.session.api_call(call_name="send_direct_message", recipient_id=recipient_id, text=text)
if val != None:
if self.session.settings["general"]["reverse_timelines"] == False:
self.session.db["sent_direct_messages"]["items"].append(val["event"])
self.session.db["sent_direct_messages"].append(val)
else:
self.session.db["sent_direct_messages"]["items"].insert(0, val["event"])
pub.sendMessage("sent-dm", data=val["event"], user=self.session.db["user_name"])
self.session.db["sent_direct_messages"].insert(0, val)
pub.sendMessage("sent-dm", data=val, user=self.session.db["user_name"])
if hasattr(dm.message, "destroy"): dm.message.destroy()
@_tweets_exist
def share_item(self, *args, **kwargs):
tweet = self.get_right_tweet()
id = tweet["id"]
id = tweet.id
if self.session.settings["general"]["retweet_mode"] == "ask":
answer = commonMessageDialogs.retweet_question(self.buffer)
if answer == widgetUtils.YES:
@ -494,40 +495,40 @@ class baseBufferController(baseBuffers.buffer):
def _retweet_with_comment(self, tweet, id, comment=''):
# If quoting a retweet, let's quote the original tweet instead the retweet.
if "retweeted_status" in tweet:
tweet = tweet["retweeted_status"]
if "full_text" in tweet:
comments = tweet["full_text"]
if hasattr(tweet, "retweeted_status"):
tweet = tweet.retweeted_status
if hasattr(tweet, "full_text"):
comments = tweet.full_text
else:
comments = tweet["text"]
retweet = messages.tweet(self.session, _(u"Quote"), _(u"Add your comment to the tweet"), u"“@%s: %s" % (tweet["user"]["screen_name"], comments), max=256, messageType="retweet")
comments = tweet.text
retweet = messages.tweet(self.session, _(u"Quote"), _(u"Add your comment to the tweet"), u"“@%s: %s" % (tweet.user.screen_name, comments), max=256, messageType="retweet")
if comment != '':
retweet.message.set_text(comment)
if retweet.message.get_response() == widgetUtils.OK:
text = retweet.message.get_text()
text = text+" https://twitter.com/{0}/status/{1}".format(tweet["user"]["screen_name"], id)
text = text+" https://twitter.com/{0}/status/{1}".format(tweet.user.screen_name, id)
if retweet.image == None:
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:
new_item = self.session.twitter.show_status(id=item["id"], include_ext_alt_text=True, tweet_mode="extended")
new_item = self.session.twitter.get_status(id=item.id, include_ext_alt_text=True, tweet_mode="extended")
pub.sendMessage("sent-tweet", data=new_item, user=self.session.db["user_name"])
else:
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):
item = self.session.api_call(call_name="retweet", _sound="retweet_send.ogg", id=id, tweet_mode="extended")
item = self.session.api_call(call_name="retweet", _sound="retweet_send.ogg", id=id)
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")
item = self.session.twitter.get_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()
if platform.system() == "Windows" and self.session.settings["general"]["relative_times"] == True:
# fix this:
original_date = arrow.get(self.session.db[self.name][self.buffer.list.get_selected()]["created_at"], "ddd MMM D H:m:s Z YYYY", locale="en")
original_date = arrow.get(self.session.db[self.name][self.buffer.list.get_selected()].created_at, locale="en")
ts = original_date.humanize(locale=languageHandler.getLanguage())
self.buffer.list.list.SetItem(self.buffer.list.get_selected(), 2, ts)
if self.session.settings['sound']['indicate_audio'] and utils.is_audio(tweet):
@ -589,22 +590,22 @@ class baseBufferController(baseBuffers.buffer):
if answer == widgetUtils.YES:
try:
if self.name == "direct_messages" or self.name == "sent_direct_messages":
self.session.twitter.destroy_direct_message(id=self.get_right_tweet()["id"])
self.session.db[self.name]["items"].pop(index)
self.session.twitter.destroy_direct_message(id=self.get_right_tweet().id)
self.session.db[self.name].pop(index)
else:
self.session.twitter.destroy_status(id=self.get_right_tweet()["id"])
self.session.twitter.destroy_status(id=self.get_right_tweet().id)
self.session.db[self.name].pop(index)
self.buffer.list.remove_item(index)
except TwythonError:
except TweepError:
self.session.sound.play("error.ogg")
@_tweets_exist
def user_details(self):
tweet = self.get_right_tweet()
if self.type == "dm":
users = [self.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
users = [self.session.get_user(tweet.message_create["sender_id"]).screen_name]
elif self.type == "people":
users = [tweet["screen_name"]]
users = [tweet.screen_name]
else:
users = utils.get_all_users(tweet, self.session.db)
dlg = dialogs.utils.selectUserDialog(title=_(u"User details"), users=users)
@ -613,81 +614,88 @@ class baseBufferController(baseBuffers.buffer):
if hasattr(dlg, "destroy"): dlg.destroy()
def get_quoted_tweet(self, tweet):
# try:
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"])
except IndexError: pass
# except TwythonError as e:
# utils.twitter_error(e)
# return
quoted_tweet = self.session.twitter.get_status(id=tweet.id)
quoted_tweet.text = utils.find_urls_in_text(quoted_tweet.text, quoted_tweet.entities)
l = tweets.is_long(quoted_tweet)
id = tweets.get_id(l)
# try:
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"])
except IndexError: pass
original_tweet = self.session.twitter.get_status(id=id)
original_tweet.text = utils.find_urls_in_text(original_tweet.text, original_tweet.entities)
return compose.compose_quoted_tweet(quoted_tweet, original_tweet, self.session.db, self.session.settings["general"]["relative_times"])
def open_in_browser(self, *args, **kwargs):
tweet = self.get_tweet()
output.speak(_(u"Opening item in web browser..."))
url = "https://twitter.com/{screen_name}/status/{tweet_id}".format(screen_name=tweet["user"]["screen_name"], tweet_id=tweet["id"])
url = "https://twitter.com/{screen_name}/status/{tweet_id}".format(screen_name=tweet.user.screen_name, tweet_id=tweet.id)
webbrowser.open(url)
class directMessagesController(baseBufferController):
def get_more_items(self):
# 50 results are allowed per API call, so let's assume max value can be 50.
# reference: https://developer.twitter.com/en/docs/twitter-api/v1/direct-messages/sending-and-receiving/api-reference/list-events
if self.session.settings["general"]["max_tweets_per_call"] > 50:
count = 50
else:
count = self.session.settings["general"]["max_tweets_per_call"]
total = 0
# try to retrieve the cursor for the current buffer.
cursor = self.session.db["cursors"].get(self.name)
try:
items = self.session.get_more_items(self.function, dm=True, name=self.name, count=self.session.settings["general"]["max_tweets_per_call"], cursor=self.session.db[self.name]["cursor"], *self.args, **self.kwargs)
except TwythonError as e:
output.speak(e.message, True)
items = getattr(self.session.twitter, self.function)(return_cursors=True, cursor=cursor, count=count, *self.args, **self.kwargs)
if type(items) == tuple:
items, cursor = items
if type(cursor) == tuple:
cursor = cursor[1]
self.session.db["cursors"][self.name] = cursor
results = [i for i in items]
items = results
log.debug("Retrieved %d items for cursored search in function %s" % (len(items), self.function))
except TweepError as e:
log.error("Error %s: %s" % (e.api_code, e.reason))
return
if items == None:
return
sent = []
received = []
for i in items:
if i["message_create"]["sender_id"] == self.session.db["user_id"]:
if int(i.message_create["sender_id"]) == self.session.db["user_id"]:
if self.session.settings["general"]["reverse_timelines"] == False:
self.session.db["sent_direct_messages"]["items"].insert(0, i)
else:
self.session.db["sent_direct_messages"]["items"].append(i)
self.session.db["sent_direct_messages"].insert(0, i)
sent.append(i)
else:
if self.session.settings["general"]["reverse_timelines"] == False:
self.session.db[self.name]["items"].insert(0, i)
self.session.db["sent_direct_messages"].append(i)
sent.insert(0, i)
else:
self.session.db[self.name]["items"].append(i)
if self.session.settings["general"]["reverse_timelines"] == False:
self.session.db[self.name].insert(0, i)
received.append(i)
else:
self.session.db[self.name].append(i)
received.insert(0, i)
total = total+1
user_ids = [item.message_create["sender_id"] for item in items]
self.session.save_users(user_ids)
pub.sendMessage("more-sent-dms", data=sent, account=self.session.db["user_name"])
selected = self.buffer.list.get_selected()
if self.session.settings["general"]["reverse_timelines"] == True:
for i in items:
if i["message_create"]["sender_id"] == self.session.db["user_id"]:
for i in received:
if int(i.message_create["sender_id"]) == self.session.db["user_id"]:
continue
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session)
self.buffer.list.insert_item(True, *tweet)
self.buffer.list.select_item(selected)
else:
for i in items:
if i["message_create"]["sender_id"] == self.session.db["user_id"]:
for i in received:
if int(i.message_create["sender_id"]) == self.session.db["user_id"]:
continue
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session)
self.buffer.list.insert_item(True, *tweet)
output.speak(_(u"%s items retrieved") % (len(items)), True)
def get_tweet(self):
tweet = self.session.db[self.name]["items"][self.buffer.list.get_selected()]
return tweet
get_right_tweet = get_tweet
output.speak(_(u"%s items retrieved") % (total), True)
@_tweets_exist
def reply(self, *args, **kwargs):
tweet = self.get_right_tweet()
screen_name = self.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]
screen_name = self.session.get_user(tweet.message_create["sender_id"]).screen_name
message = messages.reply(self.session, _(u"Mention"), _(u"Mention to %s") % (screen_name,), "@%s " % (screen_name,), [screen_name,])
if message.message.get_response() == widgetUtils.OK:
if config.app["app-settings"]["remember_mention_and_longtweet"]:
@ -705,7 +713,7 @@ class directMessagesController(baseBufferController):
tweet = self.get_tweet()
if platform.system() == "Windows" and self.session.settings["general"]["relative_times"] == True:
# fix this:
original_date = arrow.get(int(tweet["created_timestamp"][:-3]))
original_date = arrow.get(int(tweet.created_timestamp))
ts = original_date.humanize(locale=languageHandler.getLanguage())
self.buffer.list.list.SetItem(self.buffer.list.get_selected(), 2, ts)
if self.session.settings['sound']['indicate_audio'] and utils.is_audio(tweet):
@ -716,15 +724,15 @@ class directMessagesController(baseBufferController):
def clear_list(self):
dlg = commonMessageDialogs.clear_list()
if dlg == widgetUtils.YES:
self.session.db[self.name]["items"] = []
self.session.db[self.name] = []
self.buffer.list.clear()
def auto_read(self, number_of_items):
if number_of_items == 1 and self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
if self.session.settings["general"]["reverse_timelines"] == False:
tweet = self.session.db[self.name]["items"][-1]
tweet = self.session.db[self.name][-1]
else:
tweet = self.session.db[self.name]["items"][0]
tweet = self.session.db[self.name][0]
output.speak(_(u"New direct message"))
output.speak(" ".join(self.compose_function(tweet, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session)))
elif number_of_items > 1 and self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
@ -738,7 +746,7 @@ class sentDirectMessagesController(directMessagesController):
def __init__(self, *args, **kwargs):
super(sentDirectMessagesController, self).__init__(*args, **kwargs)
if ("sent_direct_messages" in self.session.db) == False:
self.session.db["sent_direct_messages"] = {"items": []}
self.session.db["sent_direct_messages"] = []
def get_more_items(self):
output.speak(_(u"Getting more items cannot be done in this buffer. Use the direct messages buffer instead."))
@ -750,11 +758,11 @@ class sentDirectMessagesController(directMessagesController):
if self.session.settings["general"]["reverse_timelines"] == True:
for i in items:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session)
self.buffer.list.insert_item(True, *tweet)
self.buffer.list.insert_item(False, *tweet)
else:
for i in items:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session)
self.buffer.list.insert_item(True, *tweet)
self.buffer.list.insert_item(False, *tweet)
class listBufferController(baseBufferController):
def __init__(self, parent, function, name, sessionObject, account, sound=None, bufferType=None, list_id=None, *args, **kwargs):
@ -768,13 +776,9 @@ class listBufferController(baseBufferController):
super(listBufferController, self).start_stream(mandatory, play_sound, avoid_autoreading)
def get_user_ids(self):
next_cursor = -1
while(next_cursor):
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"])
next_cursor = users["next_cursor"]
for i in Cursor(self.session.twitter.list_members, list_id=self.list_id, include_entities=False, skip_status=True, count=5000).items():
if i.id not in self.users:
self.users.append(i.id)
def remove_buffer(self, force=False):
if force == False:
@ -854,7 +858,7 @@ class peopleBufferController(baseBufferController):
@_tweets_exist
def reply(self, *args, **kwargs):
tweet = self.get_right_tweet()
screen_name = tweet["screen_name"]
screen_name = tweet.screen_name
message = messages.reply(self.session, _(u"Mention"), _(u"Mention to %s") % (screen_name,), "@%s " % (screen_name,), [screen_name,])
if message.message.get_response() == widgetUtils.OK:
if config.app["app-settings"]["remember_mention_and_longtweet"]:
@ -875,31 +879,55 @@ class peopleBufferController(baseBufferController):
self.execution_time = current_time
log.debug("Starting stream for %s buffer, %s account" % (self.name, self.account,))
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
val = self.session.get_cursored_stream(self.name, self.function, *self.args, **self.kwargs)
self.put_items_on_list(val)
try:
val = getattr(self.session.twitter, self.function)(return_cursors=True, count=self.session.settings["general"]["max_tweets_per_call"], *self.args, **self.kwargs)
if type(val) == tuple:
val, cursor = val
if type(cursor) == tuple:
cursor = cursor[1]
self.session.db["cursors"][self.name] = cursor
results = [i for i in val]
val = results
val.reverse()
log.debug("Retrieved %d items from cursored search in function %s" % (len(val), self.function))
except TweepError as e:
log.error("Error %s: %s" % (e.api_code, e.reason))
return
number_of_items = self.session.order_people(self.name, val)
log.debug("Number of items retrieved: %d" % (number_of_items,))
self.put_items_on_list(number_of_items)
if hasattr(self, "finished_timeline") and self.finished_timeline == False:
self.username = self.session.api_call("show_user", **self.kwargs)["screen_name"]
self.username = self.session.api_call("get_user", **self.kwargs).screen_name
self.finished_timeline = True
if val > 0 and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
if number_of_items > 0 and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
self.session.sound.play(self.sound)
# Autoread settings
if avoid_autoreading == False and mandatory == True and val > 0 and self.name in self.session.settings["other_buffers"]["autoread_buffers"]:
self.auto_read(val)
return val
if avoid_autoreading == False and mandatory == True and number_of_items > 0 and self.name in self.session.settings["other_buffers"]["autoread_buffers"]:
self.auto_read(number_of_items)
return number_of_items
def get_more_items(self):
try:
items = self.session.get_more_items(self.function, users=True, name=self.name, count=self.session.settings["general"]["max_tweets_per_call"], cursor=self.session.db[self.name]["cursor"], *self.args, **self.kwargs)
except TwythonError as e:
output.speak(e.message, True)
cursor = self.session.db["cursors"].get(self.name)
items = getattr(self.session.twitter, self.function)(return_cursors=True, users=True, cursor=cursor, count=self.session.settings["general"]["max_tweets_per_call"], *self.args, **self.kwargs)
if type(items) == tuple:
items, cursor = items
if type(cursor) == tuple:
cursor = cursor[1]
self.session.db["cursors"][self.name] = cursor
results = [i for i in items]
items = results
log.debug("Retrieved %d items from cursored search in function %s" % (len(items), self.function))
except TweepError as e:
log.error("Error %s: %s" % (e.api_code, e.reason))
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)
self.session.db[self.name].insert(0, i)
else:
self.session.db[self.name]["items"].append(i)
self.session.db[self.name].append(i)
selected = self.buffer.list.get_selected()
if self.session.settings["general"]["reverse_timelines"] == True:
for i in items:
@ -916,18 +944,18 @@ class peopleBufferController(baseBufferController):
log.debug("The list contains %d items" % (self.buffer.list.get_count(),))
# log.debug("Putting %d items on the list..." % (number_of_items,))
if self.buffer.list.get_count() == 0:
for i in self.session.db[self.name]["items"]:
for i in self.session.db[self.name]:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session)
self.buffer.list.insert_item(False, *tweet)
self.buffer.set_position(self.session.settings["general"]["reverse_timelines"])
# self.buffer.set_list_position()
elif self.buffer.list.get_count() > 0:
if self.session.settings["general"]["reverse_timelines"] == False:
for i in self.session.db[self.name]["items"][len(self.session.db[self.name]["items"])-number_of_items:]:
for i in self.session.db[self.name][len(self.session.db[self.name])-number_of_items:]:
tweet = self.compose_function(i, self.session.db)
self.buffer.list.insert_item(False, *tweet)
else:
items = self.session.db[self.name]["items"][0:number_of_items]
items = self.session.db[self.name][0:number_of_items]
items.reverse()
for i in items:
tweet = self.compose_function(i, self.session.db)
@ -935,7 +963,7 @@ class peopleBufferController(baseBufferController):
log.debug("now the list contains %d items" % (self.buffer.list.get_count(),))
def get_right_tweet(self):
tweet = self.session.db[self.name]["items"][self.buffer.list.get_selected()]
tweet = self.session.db[self.name][self.buffer.list.get_selected()]
return tweet
def add_new_item(self, item):
@ -950,12 +978,12 @@ class peopleBufferController(baseBufferController):
def clear_list(self):
dlg = commonMessageDialogs.clear_list()
if dlg == widgetUtils.YES:
self.session.db[self.name]["items"] = []
self.session.db[self.name]["cursor"] = -1
self.session.db[self.name] = []
self.session.db["cursors"][self.name] = -1
self.buffer.list.clear()
def interact(self):
user.profileController(self.session, user=self.get_right_tweet()["screen_name"])
user.profileController(self.session, user=self.get_right_tweet().screen_name)
def show_menu(self, ev, pos=0, *args, **kwargs):
menu = menus.peoplePanelMenu()
@ -978,9 +1006,9 @@ class peopleBufferController(baseBufferController):
def auto_read(self, number_of_items):
if number_of_items == 1 and self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
if self.session.settings["general"]["reverse_timelines"] == False:
tweet = self.session.db[self.name]["items"][-1]
tweet = self.session.db[self.name][-1]
else:
tweet = self.session.db[self.name["items"]][0]
tweet = self.session.db[self.name][0]
output.speak(" ".join(self.compose_function(tweet, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session)))
elif number_of_items > 1 and self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
output.speak(_(u"{0} new followers.").format(number_of_items))
@ -988,30 +1016,10 @@ class peopleBufferController(baseBufferController):
def open_in_browser(self, *args, **kwargs):
tweet = self.get_tweet()
output.speak(_(u"Opening item in web browser..."))
url = "https://twitter.com/{screen_name}".format(screen_name=tweet["screen_name"])
url = "https://twitter.com/{screen_name}".format(screen_name=tweet.screen_name)
webbrowser.open(url)
class searchBufferController(baseBufferController):
def start_stream(self, mandatory=False, play_sound=True, avoid_autoreading=False):
# starts stream every 3 minutes.
current_time = time.time()
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True:
self.execution_time = current_time
log.debug("Starting stream for %s buffer, %s account and %s type" % (self.name, self.account, self.type))
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
log.debug("Function: %s" % (self.function,))
# try:
val = self.session.search(self.name, count=self.session.settings["general"]["max_tweets_per_call"], *self.args, **self.kwargs)
# except:
# return None
num = self.session.order_buffer(self.name, val)
self.put_items_on_list(num)
if num > 0 and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
self.session.sound.play(self.sound)
# Autoread settings
if avoid_autoreading == False and mandatory == True and num > 0 and self.name in self.session.settings["other_buffers"]["autoread_buffers"]:
self.auto_read(num)
return num
def remove_buffer(self, force=False):
if force == False:
@ -1028,105 +1036,22 @@ class searchBufferController(baseBufferController):
elif dlg == widgetUtils.NO:
return False
def get_more_items(self):
elements = []
if self.session.settings["general"]["reverse_timelines"] == False:
last_id = self.session.db[self.name][0]["id"]
else:
last_id = self.session.db[self.name][-1]["id"]
try:
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)
i = self.session.check_long_tweet(i)
elements.append(i)
if self.session.settings["general"]["reverse_timelines"] == False:
self.session.db[self.name].insert(0, i)
else:
self.session.db[self.name].append(i)
selection = self.buffer.list.get_selected()
if self.session.settings["general"]["reverse_timelines"] == False:
for i in elements:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session)
self.buffer.list.insert_item(True, *tweet)
else:
for i in items:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session)
self.buffer.list.insert_item(False, *tweet)
# self.buffer.list.select_item(selection+elements)
# else:
self.buffer.list.select_item(selection)
output.speak(_(u"%s items retrieved") % (str(len(elements))), True)
class searchPeopleBufferController(peopleBufferController):
""" This is identical to a normal peopleBufferController, except that uses the page parameter instead of a cursor."""
def __init__(self, parent, function, name, sessionObject, account, bufferType="peoplePanel", *args, **kwargs):
super(searchPeopleBufferController, self).__init__(parent, function, name, sessionObject, account, bufferType="peoplePanel", *args, **kwargs)
log.debug("Initializing buffer %s, account %s" % (name, account,))
# self.compose_function = compose.compose_followers_list
log.debug("Compose_function: %s" % (self.compose_function,))
self.args = args
self.kwargs = kwargs
self.function = function
if ("page" in self.kwargs) == False:
self.kwargs["page"] = 1
def start_stream(self, mandatory=False, play_sound=True, avoid_autoreading=True):
# starts stream every 3 minutes.
current_time = time.time()
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True:
self.execution_time = current_time
log.debug("starting stream for %s buffer, %s account and %s type" % (self.name, self.account, self.type))
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
log.debug("Function: %s" % (self.function,))
# try:
val = self.session.call_paged(self.function, *self.args, **self.kwargs)
# except:
# return
number_of_items = self.session.order_cursored_buffer(self.name, val)
log.debug("Number of items retrieved: %d" % (number_of_items,))
self.put_items_on_list(number_of_items)
if number_of_items > 0 and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
self.session.sound.play(self.sound)
# Autoread settings
if avoid_autoreading == False and mandatory == True and number_of_items > 0 and self.name in self.session.settings["other_buffers"]["autoread_buffers"]:
self.auto_read(number_of_items)
return number_of_items
self.page = 1
else:
self.page = self.kwargs.pop("page")
def get_more_items(self, *args, **kwargs):
self.kwargs["page"] += 1
try:
items = self.session.get_more_items(self.function, users=True, name=self.name, count=self.session.settings["general"]["max_tweets_per_call"], *self.args, **self.kwargs)
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)
else:
self.session.db[self.name]["items"].append(i)
selected = self.buffer.list.get_selected()
# self.put_items_on_list(len(items))
if self.session.settings["general"]["reverse_timelines"] == True:
for i in items:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session)
self.buffer.list.insert_item(True, *tweet)
self.buffer.list.select_item(selected)
else:
for i in items:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session)
self.buffer.list.insert_item(True, *tweet)
# self.buffer.list.select_item(selection)
# else:
# self.buffer.list.select_item(selection-elements)
output.speak(_(u"%s items retrieved") % (len(items)), True)
# Add 1 to the page parameter, put it in kwargs and calls to get_more_items in the parent buffer.
self.page = self.page +1
self.kwargs["page"] = self.page
super(searchPeopleBufferController, self).get_more_items(*args, **kwargs)
# remove the parameter again to make sure start_stream won't fetch items for this page indefinitely.
self.kwargs.pop("page")
def remove_buffer(self, force=False):
if force == False:
@ -1168,9 +1093,9 @@ class trendsBufferController(baseBuffers.buffer):
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory == True:
self.execution_time = current_time
try:
data = self.session.call_paged("get_place_trends", id=self.trendsFor)
except:
return
data = self.session.twitter.trends_place(id=self.trendsFor)
except TweepError as err:
log.error("Error %s: %s" % (err.api_code, err.reason))
if not hasattr(self, "name_"):
self.name_ = data[0]["locations"][0]["name"]
self.trends = data[0]["trends"]
@ -1279,23 +1204,23 @@ class conversationBufferController(searchBufferController):
self.statuses = []
self.ids = []
self.statuses.append(self.tweet)
self.ids.append(self.tweet["id"])
self.ids.append(self.tweet.id)
tweet = self.tweet
while tweet["in_reply_to_status_id"] != None:
while tweet.in_reply_to_status_id != None:
try:
tweet = self.session.twitter.show_status(id=tweet["in_reply_to_status_id"], tweet_mode="extended")
except TwythonError as err:
tweet = self.session.twitter.get_status(id=tweet.in_reply_to_status_id, tweet_mode="extended")
except TweepError as err:
break
self.statuses.insert(0, tweet)
self.ids.append(tweet["id"])
if tweet["in_reply_to_status_id"] == None:
self.kwargs["since_id"] = tweet["id"]
self.ids.append(tweet["id"])
self.ids.append(tweet.id)
if tweet.in_reply_to_status_id == None:
self.kwargs["since_id"] = tweet.id
self.ids.append(tweet.id)
val2 = self.session.search(self.name, tweet_mode="extended", *self.args, **self.kwargs)
for i in val2:
if i["in_reply_to_status_id"] in self.ids:
if i.in_reply_to_status_id in self.ids:
self.statuses.append(i)
self.ids.append(i["id"])
self.ids.append(i.id)
tweet = i
number_of_items = self.session.order_buffer(self.name, self.statuses)
log.debug("Number of items retrieved: %d" % (number_of_items,))

View File

@ -1,13 +1,14 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from builtins import object
import widgetUtils
import output
import logging
from wxUI.dialogs import lists
from twython import TwythonError
from tweepy.error import TweepError
from sessions.twitter import compose, utils
from pubsub import pub
log = logging.getLogger("controller.listsController")
class listsController(object):
def __init__(self, session, user=None):
super(listsController, self).__init__()
@ -31,7 +32,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.show_lists(reverse=True, screen_name=user)
self.lists = self.session.twitter.lists_all(reverse=True, screen_name=user)
return [compose.compose_list(item) for item in self.lists]
def create_list(self, *args, **kwargs):
@ -48,8 +49,9 @@ class listsController(object):
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:
output.speak("error %s: %s" % (e.status_code, e.msg))
except TweepError as e:
output.speak("error %s: %s" % (e.api_code, e.reason))
log.exception("error %s: %s" % (e.api_code, e.reason))
dialog.destroy()
def edit_list(self, *args, **kwargs):
@ -65,44 +67,44 @@ class listsController(object):
else:
mode = "private"
try:
self.session.twitter.update_list(list_id=list["id"], name=name, description=description, mode=mode)
self.session.twitter.update_list(list_id=list.id, name=name, description=description, mode=mode)
self.session.get_lists()
self.dialog.populate_list(self.get_all_lists(), True)
except TwythonError as e:
output.speak("error %s: %s" % (e.error_code, e.msg))
except TweepError as e:
output.speak("error %s: %s" % (e.api_code, e.reason))
dialog.destroy()
def remove_list(self, *args, **kwargs):
if self.dialog.lista.get_count() == 0: return
list = self.session.db["lists"][self.dialog.get_item()]["id"]
list = self.session.db["lists"][self.dialog.get_item()].id
if lists.remove_list() == widgetUtils.YES:
try:
self.session.twitter.delete_list(list_id=list)
self.session.twitter.destroy_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:
output.speak("error %s: %s" % (e.error_code, e.msg))
except TweepError as e:
output.speak("error %s: %s" % (e.api_code, e.reason))
def open_list_as_buffer(self, *args, **kwargs):
if self.dialog.lista.get_count() == 0: return
list = self.session.db["lists"][self.dialog.get_item()]
pub.sendMessage("create-new-buffer", buffer="list", account=self.session.db["user_name"], create=list["name"])
pub.sendMessage("create-new-buffer", buffer="list", account=self.session.db["user_name"], create=list.name)
def subscribe(self, *args, **kwargs):
if self.dialog.lista.get_count() == 0: return
list_id = self.lists[self.dialog.get_item()]["id"]
list_id = self.lists[self.dialog.get_item()].id
try:
list = self.session.twitter.subscribe_to_list(list_id=list_id)
item = utils.find_item(list["id"], self.session.db["lists"])
list = self.session.twitter.subscribe_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:
output.speak("error %s: %s" % (e.status_code, e.msg))
except TweepError as e:
output.speak("error %s: %s" % (e.api_code, e.reason))
def unsubscribe(self, *args, **kwargs):
if self.dialog.lista.get_count() == 0: return
list_id = self.lists[self.dialog.get_item()]["id"]
list_id = self.lists[self.dialog.get_item()].id
try:
list = self.session.twitter.unsubscribe_from_list(list_id=list_id)
list = self.session.twitter.unsubscribe_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))
except TweepError as e:
output.speak("error %s: %s" % (e.api_code, e.reason))

View File

@ -1,8 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from builtins import str
from builtins import range
from builtins import object
import platform
system = platform.system()
import application
@ -34,7 +30,7 @@ from sessions.twitter import session as session_
from pubsub import pub
import sound
import output
from twython import TwythonError, TwythonAuthError
from tweepy.error import TweepError
from mysc.thread_utils import call_threaded
from mysc.repeating_timer import RepeatingTimer
from mysc import restart
@ -257,7 +253,7 @@ class Controller(object):
# Connection checker executed each minute.
self.checker_function = RepeatingTimer(60, self.check_connection)
self.checker_function.start()
# self.checker_function.start()
self.save_db = RepeatingTimer(300, self.save_data_in_db)
self.save_db.start()
log.debug("Setting updates to buffers every %d seconds..." % (60*config.app["app-settings"]["update_period"],))
@ -304,15 +300,15 @@ class Controller(object):
self.view.add_buffer(account.buffer , name=session.db["user_name"])
for i in session.settings['general']['buffer_order']:
if i == 'home':
home = twitterBuffers.baseBufferController(self.view.nb, "get_home_timeline", "home_timeline", session, session.db["user_name"], sound="tweet_received.ogg", tweet_mode="extended")
home = twitterBuffers.baseBufferController(self.view.nb, "home_timeline", "home_timeline", session, session.db["user_name"], sound="tweet_received.ogg", tweet_mode="extended")
self.buffers.append(home)
self.view.insert_buffer(home.buffer, name=_(u"Home"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'mentions':
mentions = twitterBuffers.baseBufferController(self.view.nb, "get_mentions_timeline", "mentions", session, session.db["user_name"], sound="mention_received.ogg", tweet_mode="extended")
mentions = twitterBuffers.baseBufferController(self.view.nb, "mentions_timeline", "mentions", session, session.db["user_name"], sound="mention_received.ogg", tweet_mode="extended")
self.buffers.append(mentions)
self.view.insert_buffer(mentions.buffer, name=_(u"Mentions"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'dm':
dm = twitterBuffers.directMessagesController(self.view.nb, "get_direct_messages", "direct_messages", session, session.db["user_name"], bufferType="dmPanel", compose_func="compose_direct_message", sound="dm_received.ogg", full_text=True, items="events")
dm = twitterBuffers.directMessagesController(self.view.nb, "list_direct_messages", "direct_messages", session, session.db["user_name"], bufferType="dmPanel", compose_func="compose_direct_message", sound="dm_received.ogg")
self.buffers.append(dm)
self.view.insert_buffer(dm.buffer, name=_(u"Direct messages"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'sent_dm':
@ -320,62 +316,62 @@ class Controller(object):
self.buffers.append(sent_dm)
self.view.insert_buffer(sent_dm.buffer, name=_(u"Sent direct messages"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'sent_tweets':
sent_tweets = twitterBuffers.baseBufferController(self.view.nb, "get_user_timeline", "sent_tweets", session, session.db["user_name"], screen_name=session.db["user_name"], tweet_mode="extended")
sent_tweets = twitterBuffers.baseBufferController(self.view.nb, "user_timeline", "sent_tweets", session, session.db["user_name"], screen_name=session.db["user_name"], tweet_mode="extended")
self.buffers.append(sent_tweets)
self.view.insert_buffer(sent_tweets.buffer, name=_(u"Sent tweets"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'favorites':
favourites = twitterBuffers.baseBufferController(self.view.nb, "get_favorites", "favourites", session, session.db["user_name"], sound="favourite.ogg", tweet_mode="extended")
favourites = twitterBuffers.baseBufferController(self.view.nb, "favorites", "favourites", session, session.db["user_name"], sound="favourite.ogg", tweet_mode="extended")
self.buffers.append(favourites)
self.view.insert_buffer(favourites.buffer, name=_(u"Likes"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'followers':
followers = twitterBuffers.peopleBufferController(self.view.nb, "get_followers_list", "followers", session, session.db["user_name"], sound="update_followers.ogg", screen_name=session.db["user_name"])
followers = twitterBuffers.peopleBufferController(self.view.nb, "followers", "followers", session, session.db["user_name"], sound="update_followers.ogg", screen_name=session.db["user_name"])
self.buffers.append(followers)
self.view.insert_buffer(followers.buffer, name=_(u"Followers"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'friends':
friends = twitterBuffers.peopleBufferController(self.view.nb, "get_friends_list", "friends", session, session.db["user_name"], screen_name=session.db["user_name"])
friends = twitterBuffers.peopleBufferController(self.view.nb, "friends", "friends", session, session.db["user_name"], screen_name=session.db["user_name"])
self.buffers.append(friends)
self.view.insert_buffer(friends.buffer, name=_(u"Friends"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'blocks':
blocks = twitterBuffers.peopleBufferController(self.view.nb, "list_blocks", "blocked", session, session.db["user_name"])
blocks = twitterBuffers.peopleBufferController(self.view.nb, "blocks", "blocked", session, session.db["user_name"])
self.buffers.append(blocks)
self.view.insert_buffer(blocks.buffer, name=_(u"Blocked users"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'muted':
muted = twitterBuffers.peopleBufferController(self.view.nb, "list_mutes", "muted", session, session.db["user_name"])
muted = twitterBuffers.peopleBufferController(self.view.nb, "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"]))
timelines = baseBuffers.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"]))
for i in session.settings["other_buffers"]["timelines"]:
tl = twitterBuffers.baseBufferController(self.view.nb, "get_user_timeline", "%s-timeline" % (i,), session, session.db["user_name"], sound="tweet_timeline.ogg", bufferType=None, user_id=i, tweet_mode="extended")
tl = twitterBuffers.baseBufferController(self.view.nb, "user_timeline", "%s-timeline" % (i,), session, session.db["user_name"], sound="tweet_timeline.ogg", bufferType=None, user_id=i, tweet_mode="extended")
self.buffers.append(tl)
self.view.insert_buffer(tl.buffer, name=_(u"Timeline for {}").format(i,), pos=self.view.search("timelines", session.db["user_name"]))
favs_timelines = baseBuffers.emptyPanel(self.view.nb, "favs_timelines", session.db["user_name"])
self.buffers.append(favs_timelines)
self.view.insert_buffer(favs_timelines.buffer , name=_(u"Likes timelines"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
for i in session.settings["other_buffers"]["favourites_timelines"]:
tl = twitterBuffers.baseBufferController(self.view.nb, "get_favorites", "%s-favorite" % (i,), session, session.db["user_name"], bufferType=None, sound="favourites_timeline_updated.ogg", user_id=i, tweet_mode="extended")
tl = twitterBuffers.baseBufferController(self.view.nb, "favorites", "%s-favorite" % (i,), session, session.db["user_name"], bufferType=None, sound="favourites_timeline_updated.ogg", user_id=i, tweet_mode="extended")
self.buffers.append(tl)
self.view.insert_buffer(tl.buffer, name=_(u"Likes for {}").format(i,), pos=self.view.search("favs_timelines", session.db["user_name"]))
followers_timelines = baseBuffers.emptyPanel(self.view.nb, "followers_timelines", session.db["user_name"])
self.buffers.append(followers_timelines)
self.view.insert_buffer(followers_timelines.buffer , name=_(u"Followers' Timelines"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
for i in session.settings["other_buffers"]["followers_timelines"]:
tl = twitterBuffers.peopleBufferController(self.view.nb, "get_followers_list", "%s-followers" % (i,), session, session.db["user_name"], sound="new_event.ogg", user_id=i)
tl = twitterBuffers.peopleBufferController(self.view.nb, "followers", "%s-followers" % (i,), session, session.db["user_name"], sound="new_event.ogg", user_id=i)
self.buffers.append(tl)
self.view.insert_buffer(tl.buffer, name=_(u"Followers for {}").format(i,), pos=self.view.search("followers_timelines", session.db["user_name"]))
friends_timelines = baseBuffers.emptyPanel(self.view.nb, "friends_timelines", session.db["user_name"])
self.buffers.append(friends_timelines)
self.view.insert_buffer(friends_timelines.buffer , name=_(u"Friends' Timelines"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
for i in session.settings["other_buffers"]["friends_timelines"]:
tl = twitterBuffers.peopleBufferController(self.view.nb, "get_friends_list", "%s-friends" % (i,), session, session.db["user_name"], sound="new_event.ogg", user_id=i)
tl = twitterBuffers.peopleBufferController(self.view.nb, "friends", "%s-friends" % (i,), session, session.db["user_name"], sound="new_event.ogg", user_id=i)
self.buffers.append(tl)
self.view.insert_buffer(tl.buffer, name=_(u"Friends for {}").format(i,), pos=self.view.search("friends_timelines", session.db["user_name"]))
lists = baseBuffers.emptyPanel(self.view.nb, "lists", session.db["user_name"])
self.buffers.append(lists)
self.view.insert_buffer(lists.buffer , name=_(u"Lists"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
for i in session.settings["other_buffers"]["lists"]:
tl = twitterBuffers.listBufferController(self.view.nb, "get_list_statuses", "%s-list" % (i,), session, session.db["user_name"], bufferType=None, sound="list_tweet.ogg", list_id=utils.find_list(i, session.db["lists"]), tweet_mode="extended")
tl = twitterBuffers.listBufferController(self.view.nb, "list_timeline", "%s-list" % (i,), session, session.db["user_name"], bufferType=None, sound="list_tweet.ogg", list_id=utils.find_list(i, session.db["lists"]), tweet_mode="extended")
session.lists.append(tl)
self.buffers.append(tl)
self.view.insert_buffer(tl.buffer, name=_(u"List for {}").format(i), pos=self.view.search("lists", session.db["user_name"]))
@ -530,9 +526,9 @@ class Controller(object):
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type == "people":
users = [tweet["screen_name"]]
users = [tweet.screen_name]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name]
else:
users = utils.get_all_users(tweet, buff.session.db)
dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users)
@ -547,9 +543,9 @@ class Controller(object):
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type == "people":
users = [tweet["screen_name"]]
users = [tweet.screen_name]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name]
else:
users = utils.get_all_users(tweet, buff.session.db)
dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users)
@ -561,23 +557,23 @@ 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.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"])
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)
except TwythonError as e:
output.speak("error %s: %s" % (e.error_code, e.msg))
except TweepError as e:
output.speak("error %s: %s" % (e.api_code, e.reason))
def remove_from_list(self, *args, **kwargs):
buff = self.get_best_buffer()
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type == "people":
users = [tweet["screen_name"]]
users = [tweet.screen_name]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name]
else:
users = utils.get_all_users(tweet, buff.session.db)
dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users)
@ -589,14 +585,14 @@ 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.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"])
list = buff.session.twitter.remove_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)
except TwythonError as e:
output.speak("error %s: %s" % (e.error_code, e.msg))
except TweepError as e:
output.speak("error %s: %s" % (e.api_code, e.reason))
def list_manager(self, *args, **kwargs):
s = self.get_best_buffer().session
@ -669,9 +665,9 @@ class Controller(object):
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type == "people":
users = [tweet["screen_name"]]
users = [tweet.screen_name]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name]
else:
users = utils.get_all_users(tweet, buff.session.db)
u = userActionsController.userActionsController(buff, users)
@ -681,9 +677,9 @@ class Controller(object):
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type == "people":
users = [tweet["screen_name"]]
users = [tweet.screen_name]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name]
else:
users = utils.get_all_users(tweet, buff.session.db)
u = userActionsController.userActionsController(buff, users, "unfollow")
@ -693,9 +689,9 @@ class Controller(object):
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type == "people":
users = [tweet["screen_name"]]
users = [tweet.screen_name]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name]
else:
users = utils.get_all_users(tweet, buff.session.db)
u = userActionsController.userActionsController(buff, users, "mute")
@ -705,9 +701,9 @@ class Controller(object):
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type == "people":
users = [tweet["screen_name"]]
users = [tweet.screen_name]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name]
else:
users = utils.get_all_users(tweet, buff.session.db)
u = userActionsController.userActionsController(buff, users, "unmute")
@ -717,9 +713,9 @@ class Controller(object):
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type == "people":
users = [tweet["screen_name"]]
users = [tweet.screen_name]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name]
else:
users = utils.get_all_users(tweet, buff.session.db)
u = userActionsController.userActionsController(buff, users, "block")
@ -729,9 +725,9 @@ class Controller(object):
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type == "people":
users = [tweet["screen_name"]]
users = [tweet.screen_name]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name]
else:
users = utils.get_all_users(tweet, buff.session.db)
u = userActionsController.userActionsController(buff, users, "unblock")
@ -741,9 +737,9 @@ class Controller(object):
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type == "people":
users = [tweet["screen_name"]]
users = [tweet.screen_name]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name]
else:
users = utils.get_all_users(tweet, buff.session.db)
u = userActionsController.userActionsController(buff, users, "report")
@ -775,7 +771,7 @@ class Controller(object):
if buffer.type == "dm" or buffer.type == "people" or buffer.type == "events":
return
else:
id = buffer.get_tweet()["id"]
id = buffer.get_tweet().id
call_threaded(buffer.session.api_call, call_name="create_favorite", _sound="favourite.ogg", id=id)
def remove_from_favourites(self, *args, **kwargs):
@ -783,7 +779,7 @@ class Controller(object):
if buffer.type == "dm" or buffer.type == "people" or buffer.type == "events":
return
else:
id = buffer.get_tweet()["id"]
id = buffer.get_tweet().id
call_threaded(buffer.session.api_call, call_name="destroy_favorite", id=id)
def toggle_like(self, *args, **kwargs):
@ -791,9 +787,9 @@ class Controller(object):
if buffer.type == "dm" or buffer.type == "people" or buffer.type == "events":
return
else:
id = buffer.get_tweet()["id"]
tweet = buffer.session.twitter.show_status(id=id, include_ext_alt_text=True, tweet_mode="extended")
if tweet["favorited"] == False:
id = buffer.get_tweet().id
tweet = buffer.session.twitter.get_status(id=id, include_ext_alt_text=True, tweet_mode="extended")
if tweet.favorited == False:
call_threaded(buffer.session.api_call, call_name="create_favorite", _sound="favourite.ogg", id=id)
else:
call_threaded(buffer.session.api_call, call_name="destroy_favorite", id=id)
@ -808,7 +804,7 @@ class Controller(object):
elif buffer.type == "dm":
non_tweet = buffer.get_formatted_message()
item = buffer.get_right_tweet()
original_date = arrow.get(int(item["created_timestamp"][:-3]))
original_date = arrow.get(int(item.created_timestamp))
date = original_date.shift(seconds=buffer.session.db["utc_offset"]).format(_(u"MMM D, YYYY. H:m"), locale=languageHandler.getLanguage())
msg = messages.viewTweet(non_tweet, [], False, date=date)
else:
@ -828,9 +824,9 @@ class Controller(object):
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type == "people":
users = [tweet["screen_name"]]
users = [tweet.screen_name]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name]
else:
users = utils.get_all_users(tweet, buff.session.db)
dlg = dialogs.userSelection.selectUserDialog(users=users, default=default)
@ -840,85 +836,85 @@ class Controller(object):
if usr == dlg.get_user():
commonMessageDialogs.suspended_user()
return
if usr["protected"] == True:
if usr["following"] == False:
if usr.protected == True:
if usr.following == False:
commonMessageDialogs.no_following()
return
tl_type = dlg.get_action()
if tl_type == "tweets":
if usr["statuses_count"] == 0:
if usr.statuses_count == 0:
commonMessageDialogs.no_tweets()
return
if usr["id_str"] in buff.session.settings["other_buffers"]["timelines"]:
if usr.id_str in buff.session.settings["other_buffers"]["timelines"]:
commonMessageDialogs.timeline_exist()
return
tl = twitterBuffers.baseBufferController(self.view.nb, "get_user_timeline", "%s-timeline" % (usr["id_str"],), buff.session, buff.session.db["user_name"], bufferType=None, sound="tweet_timeline.ogg", user_id=usr["id_str"], tweet_mode="extended")
tl = twitterBuffers.baseBufferController(self.view.nb, "user_timeline", "%s-timeline" % (usr.id_str,), buff.session, buff.session.db["user_name"], bufferType=None, sound="tweet_timeline.ogg", user_id=usr.id_str, tweet_mode="extended")
try:
tl.start_stream(play_sound=False)
except TwythonAuthError:
except ValueError:
commonMessageDialogs.unauthorized()
return
pos=self.view.search("timelines", buff.session.db["user_name"])
self.insert_buffer(tl, pos+1)
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"])
buff.session.settings["other_buffers"]["timelines"].append(usr.id_str)
pub.sendMessage("buffer-title-changed", buffer=tl)
buff.session.sound.play("create_timeline.ogg")
elif tl_type == "favourites":
if usr["favourites_count"] == 0:
if usr.favourites_count == 0:
commonMessageDialogs.no_favs()
return
if usr["id_str"] in buff.session.settings["other_buffers"]["favourites_timelines"]:
if usr.id_str in buff.session.settings["other_buffers"]["favourites_timelines"]:
commonMessageDialogs.timeline_exist()
return
tl = twitterBuffers.baseBufferController(self.view.nb, "get_favorites", "%s-favorite" % (usr["id_str"],), buff.session, buff.session.db["user_name"], bufferType=None, sound="favourites_timeline_updated.ogg", user_id=usr["id_str"], tweet_mode="extended")
tl = twitterBuffers.baseBufferController(self.view.nb, "favorites", "%s-favorite" % (usr.id_str,), buff.session, buff.session.db["user_name"], bufferType=None, sound="favourites_timeline_updated.ogg", user_id=usr.id_str, tweet_mode="extended")
try:
tl.start_stream(play_sound=False)
except TwythonAuthError:
except ValueError:
commonMessageDialogs.unauthorized()
return
pos=self.view.search("favs_timelines", buff.session.db["user_name"])
self.insert_buffer(tl, pos+1)
self.view.insert_buffer(buffer=tl.buffer, name=_(u"Likes for {}").format(dlg.get_user()), pos=pos)
buff.session.settings["other_buffers"]["favourites_timelines"].append(usr["id_str"])
buff.session.settings["other_buffers"]["favourites_timelines"].append(usr.id_str)
pub.sendMessage("buffer-title-changed", buffer=buff)
buff.session.sound.play("create_timeline.ogg")
elif tl_type == "followers":
if usr["followers_count"] == 0:
if usr.followers_count == 0:
commonMessageDialogs.no_followers()
return
if usr["id_str"] in buff.session.settings["other_buffers"]["followers_timelines"]:
if usr.id_str in buff.session.settings["other_buffers"]["followers_timelines"]:
commonMessageDialogs.timeline_exist()
return
tl = twitterBuffers.peopleBufferController(self.view.nb, "get_followers_list", "%s-followers" % (usr["id_str"],), buff.session, buff.session.db["user_name"], sound="new_event.ogg", user_id=usr["id_str"])
tl = twitterBuffers.peopleBufferController(self.view.nb, "followers", "%s-followers" % (usr.id_str,), buff.session, buff.session.db["user_name"], sound="new_event.ogg", user_id=usr.id_str)
try:
tl.start_stream(play_sound=False)
except TwythonAuthError:
except ValueError:
commonMessageDialogs.unauthorized()
return
pos=self.view.search("followers_timelines", buff.session.db["user_name"])
self.insert_buffer(tl, pos+1)
self.view.insert_buffer(buffer=tl.buffer, name=_(u"Followers for {}").format(dlg.get_user()), pos=pos)
buff.session.settings["other_buffers"]["followers_timelines"].append(usr["id_str"])
buff.session.settings["other_buffers"]["followers_timelines"].append(usr.id_str)
buff.session.sound.play("create_timeline.ogg")
pub.sendMessage("buffer-title-changed", buffer=i)
elif tl_type == "friends":
if usr["friends_count"] == 0:
if usr.friends_count == 0:
commonMessageDialogs.no_friends()
return
if usr["id_str"] in buff.session.settings["other_buffers"]["friends_timelines"]:
if usr.id_str in buff.session.settings["other_buffers"]["friends_timelines"]:
commonMessageDialogs.timeline_exist()
return
tl = twitterBuffers.peopleBufferController(self.view.nb, "get_friends_list", "%s-friends" % (usr["id_str"],), buff.session, buff.session.db["user_name"], sound="new_event.ogg", user_id=usr["id_str"])
tl = twitterBuffers.peopleBufferController(self.view.nb, "friends", "%s-friends" % (usr.id_str,), buff.session, buff.session.db["user_name"], sound="new_event.ogg", user_id=usr.id_str)
try:
tl.start_stream(play_sound=False)
except TwythonAuthError:
except ValueError:
commonMessageDialogs.unauthorized()
return
pos=self.view.search("friends_timelines", buff.session.db["user_name"])
self.insert_buffer(tl, pos+1)
self.view.insert_buffer(buffer=tl.buffer, name=_(u"Friends for {}").format(dlg.get_user()), pos=pos)
buff.session.settings["other_buffers"]["friends_timelines"].append(usr["id_str"])
buff.session.settings["other_buffers"]["friends_timelines"].append(usr.id_str)
buff.session.sound.play("create_timeline.ogg")
pub.sendMessage("buffer-title-changed", buffer=i)
else:
@ -927,8 +923,8 @@ class Controller(object):
def open_conversation(self, *args, **kwargs):
buffer = self.get_current_buffer()
id = buffer.get_right_tweet()["id_str"]
user = buffer.get_right_tweet()["user"]["screen_name"]
id = buffer.get_right_tweet().id_str
user = buffer.get_right_tweet().user.screen_name
search = twitterBuffers.conversationBufferController(self.view.nb, "search", "%s-searchterm" % (id,), buffer.session, buffer.session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", since_id=id, q="@{0}".format(user,))
search.tweet = buffer.get_right_tweet()
search.start_stream(start=True)
@ -968,9 +964,9 @@ class Controller(object):
def reverse_geocode(self, event=None):
try:
tweet = self.get_current_buffer().get_tweet()
if tweet["coordinates"] != None:
x = tweet["coordinates"]["coordinates"][0]
y = tweet["coordinates"]["coordinates"][1]
if tweet.coordinates != None:
x = tweet.coordinates["coordinates"][0]
y = tweet.coordinates["coordinates"][1]
address = geocoder.reverse_geocode(y, x, language = languageHandler.curLang)
if event == None: output.speak(address[0].__str__())
else: self.view.show_address(address[0].__str__())
@ -988,9 +984,9 @@ class Controller(object):
def view_reverse_geocode(self, event=None):
try:
tweet = self.get_current_buffer().get_right_tweet()
if tweet["coordinates"] != None:
x = tweet["coordinates"]["coordinates"][0]
y = tweet["coordinates"]["coordinates"][1]
if tweet.coordinates != None:
x = tweet.coordinates["coordinates"][0]
y = tweet.coordinates["coordinates"][1]
address = geocoder.reverse_geocode(y, x, language = languageHandler.curLang)
dlg = commonMessageDialogs.view_geodata(address[0].__str__())
else:
@ -1330,7 +1326,11 @@ class Controller(object):
i.start_stream()
else:
i.start_stream(play_sound=False)
except TwythonAuthError:
except TweepError as err:
log.exception("Error %s starting buffer %s on account %s, with args %r and kwargs %r due to the following reason: %s" % (err.api_code, i.name, i.account, i.args, i.kwargs, err.reason))
# Determine if this error was caused by a block applied to the current user (IE permission errors).
errors_allowed = [130]
if (err.api_code != None and err.api_code not in errors_allowed) or (err.api_code == None and 'Not authorized' in err.reason): # A twitter error, so safely try to remove the buffer.
buff = self.view.search(i.name, i.account)
i.remove_buffer(force=True)
commonMessageDialogs.blocked_timeline()
@ -1354,34 +1354,34 @@ class Controller(object):
try:
if sessions.sessions[i].is_logged == False: continue
sessions.sessions[i].check_connection()
except TwythonError: # We shouldn't allow this function to die.
except TweepError: # We shouldn't allow this function to die.
pass
def create_new_buffer(self, buffer, account, create):
buff = self.search_buffer("home_timeline", account)
if create == True:
if buffer == "favourites":
favourites = twitterBuffers.baseBufferController(self.view.nb, "get_favorites", "favourites", buff.session, buff.session.db["user_name"], tweet_mode="extended")
favourites = twitterBuffers.baseBufferController(self.view.nb, "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)
if buffer == "followers":
followers = twitterBuffers.peopleBufferController(self.view.nb, "get_followers_list", "followers", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"])
followers = twitterBuffers.peopleBufferController(self.view.nb, "followers", "followers", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"])
self.buffers.append(followers)
self.view.insert_buffer(followers.buffer, name=_(u"Followers"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"]))
followers.start_stream(play_sound=False)
elif buffer == "friends":
friends = twitterBuffers.peopleBufferController(self.view.nb, "get_friends_list", "friends", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"])
friends = twitterBuffers.peopleBufferController(self.view.nb, "friends", "friends", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"])
self.buffers.append(friends)
self.view.insert_buffer(friends.buffer, name=_(u"Friends"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"]))
friends.start_stream(play_sound=False)
elif buffer == "blocked":
blocks = twitterBuffers.peopleBufferController(self.view.nb, "list_blocks", "blocked", buff.session, buff.session.db["user_name"])
blocks = twitterBuffers.peopleBufferController(self.view.nb, "blocks", "blocked", buff.session, buff.session.db["user_name"])
self.buffers.append(blocks)
self.view.insert_buffer(blocks.buffer, name=_(u"Blocked users"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"]))
blocks.start_stream(play_sound=False)
elif buffer == "muted":
muted = twitterBuffers.peopleBufferController(self.view.nb, "get_muted_users_list", "muted", buff.session, buff.session.db["user_name"])
muted = twitterBuffers.peopleBufferController(self.view.nb, "mutes", "muted", buff.session, buff.session.db["user_name"])
self.buffers.append(muted)
self.view.insert_buffer(muted.buffer, name=_(u"Muted users"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"]))
muted.start_stream(play_sound=False)
@ -1395,7 +1395,7 @@ class Controller(object):
if create in buff.session.settings["other_buffers"]["lists"]:
output.speak(_(u"This list is already opened"), True)
return
tl = twitterBuffers.listBufferController(self.view.nb, "get_list_statuses", create+"-list", buff.session, buff.session.db["user_name"], bufferType=None, list_id=utils.find_list(create, buff.session.db["lists"]), tweet_mode="extended")
tl = twitterBuffers.listBufferController(self.view.nb, "list_timeline", 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)
@ -1536,7 +1536,11 @@ class Controller(object):
if i.session != None and i.session.is_logged == True:
try:
i.start_stream(mandatory=True)
except TwythonAuthError:
except TweepError as err:
log.exception("Error %s starting buffer %s on account %s, with args %r and kwargs %r due to the following reason: %s" % (err.api_code, i.name, i.account, i.args, i.kwargs, err.reason))
# Determine if this error was caused by a block applied to the current user (IE permission errors).
errors_allowed = [130]
if (err.api_code != None and err.api_code not in errors_allowed) or (err.api_code == None and 'Not authorized' in err.reason): # A twitter error, so safely try to remove the buffer.
buff = self.view.search(i.name, i.account)
i.remove_buffer(force=True)
commonMessageDialogs.blocked_timeline()
@ -1576,12 +1580,12 @@ class Controller(object):
return
tweet = buffer.get_tweet()
media_list = []
if ("entities" in tweet) and ("media" in tweet["entities"]):
[media_list.append(i) for i in tweet["entities"]["media"] if i not in media_list]
elif "retweeted_status" in tweet and "media" in tweet["retweeted_status"]["entities"]:
[media_list.append(i) for i in tweet["retweeted_status"]["entities"]["media"] if i not in media_list]
elif "quoted_status" in tweet and "media" in tweet["quoted_status"]["entities"]:
[media_list.append(i) for i in tweet["quoted_status"]["entities"]["media"] if i not in media_list]
if hasattr(tweet, "entities") and tweet.entities.get("media") != None:
[media_list.append(i) for i in tweet.entities["media"] if i not in media_list]
elif hasattr(tweet, "retweeted_status") and tweet.retweeted_status.get("media") != None:
[media_list.append(i) for i in tweet.retweeted_status.entities["media"] if i not in media_list]
elif hasattr(tweet, "quoted_status") and tweet.quoted_status.entities.get("media") != None:
[media_list.append(i) for i in tweet.quoted_status.entities["media"] if i not in media_list]
if len(media_list) > 1:
image_list = [_(u"Picture {0}").format(i,) for i in range(0, len(media_list))]
dialog = dialogs.urlList.urlList(title=_(u"Select the picture"))
@ -1597,7 +1601,7 @@ class Controller(object):
if buffer.session.settings["mysc"]["ocr_language"] != "":
ocr_lang = buffer.session.settings["mysc"]["ocr_language"]
else:
ocr_lang = ocr.OCRSpace.short_langs.index(tweet["lang"])
ocr_lang = ocr.OCRSpace.short_langs.index(tweet.lang)
ocr_lang = ocr.OCRSpace.OcrLangs[ocr_lang]
api = ocr.OCRSpace.OCRSpaceAPI()
try:

View File

@ -1,12 +1,6 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import unicode_literals
from builtins import str
from builtins import range
from builtins import object
import re
import platform
from . import attach
import arrow
import languageHandler
system = platform.system()
@ -16,15 +10,16 @@ import url_shortener
import sound
import config
from pubsub import pub
from twitter_text import parse_tweet
if system == "Windows":
from wxUI.dialogs import message, urlList
from wxUI import commonMessageDialogs
from extra import translator, SpellChecker, autocompletionUsers
from extra.AudioUploader import audioUploader
elif system == "Linux":
from gtkUI.dialogs import message
from sessions.twitter import utils
from . import attach
class basicTweet(object):
""" This class handles the tweet main features. Other classes should derive from this class."""
@ -50,8 +45,11 @@ class basicTweet(object):
dlg = translator.gui.translateDialog()
if dlg.get_response() == widgetUtils.OK:
text_to_translate = self.message.get_text()
dest = [x[0] for x in translator.translator.available_languages()][dlg.get("dest_lang")]
msg = translator.translator.translate(text=text_to_translate, target=dest)
language_dict = translator.translator.available_languages()
for k in language_dict:
if language_dict[k] == dlg.dest_lang.GetStringSelection():
dst = k
msg = translator.translator.translate(text=text_to_translate, target=dst)
self.message.set_text(msg)
self.text_processor()
self.message.text_focus()
@ -105,8 +103,10 @@ class basicTweet(object):
self.message.disable_button("shortenButton")
self.message.disable_button("unshortenButton")
if self.message.get("long_tweet") == False:
self.message.set_title(_(u"%s - %s of %d characters") % (self.title, len(self.message.get_text()), self.max))
if len(self.message.get_text()) > self.max:
text = self.message.get_text()
results = parse_tweet(text)
self.message.set_title(_(u"%s - %s of %d characters") % (self.title, results.weightedLength, self.max))
if results.weightedLength > self.max:
self.session.sound.play("max_length.ogg")
else:
self.message.set_title(_(u"%s - %s characters") % (self.title, len(self.message.get_text())))
@ -216,56 +216,57 @@ class viewTweet(basicTweet):
text = ""
for i in range(0, len(tweetList)):
# tweets with message keys are longer tweets, the message value is the full messaje taken from twishort.
if "message" in tweetList[i] and tweetList[i]["is_quote_status"] == False:
if hasattr(tweetList[i], "message") and tweetList[i].is_quote_status == False:
value = "message"
else:
value = "full_text"
if "retweeted_status" in tweetList[i] and tweetList[i]["is_quote_status"] == False:
if ("message" in tweetList[i]) == False:
text = text + "rt @%s: %s\n" % (tweetList[i]["retweeted_status"]["user"]["screen_name"], tweetList[i]["retweeted_status"]["full_text"])
if hasattr(tweetList[i], "retweeted_status") and tweetList[i].is_quote_status == False:
if not hasattr(tweetList[i], "message"):
text = text + "rt @%s: %s\n" % (tweetList[i].retweeted_status.user.screen_name, tweetList[i].retweeted_status.full_text)
else:
text = text + "rt @%s: %s\n" % (tweetList[i]["retweeted_status"]["user"]["screen_name"], tweetList[i][value])
text = text + "rt @%s: %s\n" % (tweetList[i].retweeted_status.user.screen_name, getattr(tweetList[i], value))
else:
text = text + " @%s: %s\n" % (tweetList[i]["user"]["screen_name"], tweetList[i][value])
text = text + " @%s: %s\n" % (tweetList[i].user.screen_name, getattr(tweetList[i], value))
# tweets with extended_entities could include image descriptions.
if "extended_entities" in tweetList[i] and "media" in tweetList[i]["extended_entities"]:
for z in tweetList[i]["extended_entities"]["media"]:
if hasattr(tweetList[i], "extended_entities") and "media" in tweetList[i].extended_entities:
for z in tweetList[i].extended_entities["media"]:
if "ext_alt_text" in z and z["ext_alt_text"] != None:
image_description.append(z["ext_alt_text"])
if "retweeted_status" in tweetList[i] and "extended_entities" in tweetList[i]["retweeted_status"] and "media" in tweetList[i]["retweeted_status"]["extended_entities"]:
for z in tweetList[i]["retweeted_status"]["extended_entities"]["media"]:
if hasattr(tweetList[i], "retweeted_status") and hasattr(tweetList[i].retweeted_status, "extended_entities") and "media" in tweetList[i].retweeted_status["extended_entities"]:
for z in tweetList[i].retweeted_status.extended_entities["media"]:
if "ext_alt_text" in z and z["ext_alt_text"] != None:
image_description.append(z["ext_alt_text"])
# set rt and likes counters.
rt_count = str(tweet["retweet_count"])
favs_count = str(tweet["favorite_count"])
rt_count = str(tweet.retweet_count)
favs_count = str(tweet.favorite_count)
# Gets the client from where this tweet was made.
source = re.sub(r"(?s)<.*?>", "", tweet["source"])
original_date = arrow.get(tweet["created_at"], "ddd MMM DD H:m:s Z YYYY", locale="en")
source = tweet.source
original_date = arrow.get(tweet.created_at, locale="en")
date = original_date.shift(seconds=utc_offset).format(_(u"MMM D, YYYY. H:m"), locale=languageHandler.getLanguage())
if text == "":
if "message" in tweet:
if hasattr(tweet, "message"):
value = "message"
else:
value = "full_text"
if "retweeted_status" in tweet:
if ("message" in tweet) == False:
text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet["retweeted_status"]["full_text"])
if hasattr(tweet, "retweeted_status"):
if not hasattr(tweet, "message"):
text = "rt @%s: %s" % (tweet.retweeted_status.user.screen_name, tweet.retweeted_status.full_text)
else:
text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet[value])
text = "rt @%s: %s" % (tweet.retweeted_status.user.screen_name, getattr(tweet, value))
else:
text = tweet[value]
text = getattr(tweet, value)
text = self.clear_text(text)
if "extended_entities" in tweet and "media" in tweet["extended_entities"]:
for z in tweet["extended_entities"]["media"]:
if hasattr(tweet, "extended_entities") and "media" in tweet.extended_entities:
for z in tweet.extended_entities["media"]:
if "ext_alt_text" in z and z["ext_alt_text"] != None:
image_description.append(z["ext_alt_text"])
if "retweeted_status" in tweet and "extended_entities" in tweet["retweeted_status"] and "media" in tweet["retweeted_status"]["extended_entities"]:
for z in tweet["retweeted_status"]["extended_entities"]["media"]:
if hasattr(tweet, "retweeted_status") and hasattr(tweet.retweeted_status, "extended_entities") and "media" in tweet.retweeted_status.extended_entities:
for z in tweet.retweeted_status.extended_entities["media"]:
if "ext_alt_text" in z and z["ext_alt_text"] != None:
image_description.append(z["ext_alt_text"])
self.message = message.viewTweet(text, rt_count, favs_count, source, date)
self.message.set_title(len(text))
results = parse_tweet(text)
self.message.set_title(results.weightedLength)
[self.message.set_image_description(i) for i in image_description]
else:
self.title = _(u"View item")

View File

@ -74,12 +74,12 @@ class globalSettingsController(object):
self.dialog.set_value("general", "update_period", config.app["app-settings"]["update_period"])
self.dialog.set_value("general", "check_for_updates", config.app["app-settings"]["check_for_updates"])
self.dialog.set_value("general", "remember_mention_and_longtweet", config.app["app-settings"]["remember_mention_and_longtweet"])
proxyTypes=config.proxyTypes
self.dialog.create_proxy([_(u"Direct connection")]+proxyTypes)
if config.app["proxy"]["type"] not in proxyTypes:
proxyTypes = [_("System default"), _("HTTP"), _("SOCKS v4"), _("SOCKS v4 with DNS support"), _("SOCKS v5"), _("SOCKS v5 with DNS support")]
self.dialog.create_proxy(proxyTypes)
try:
self.dialog.proxy.type.SetSelection(config.app["proxy"]["type"])
except:
self.dialog.proxy.type.SetSelection(0)
else:
self.dialog.proxy.type.SetSelection(proxyTypes.index(config.app["proxy"]["type"])+1)
self.dialog.set_value("proxy", "server", config.app["proxy"]["server"])
self.dialog.set_value("proxy", "port", config.app["proxy"]["port"])
self.dialog.set_value("proxy", "user", config.app["proxy"]["user"])
@ -121,7 +121,7 @@ class globalSettingsController(object):
if config.app["proxy"]["type"]!=self.dialog.get_value("proxy", "type") or config.app["proxy"]["server"] != self.dialog.get_value("proxy", "server") or config.app["proxy"]["port"] != self.dialog.get_value("proxy", "port") or config.app["proxy"]["user"] != self.dialog.get_value("proxy", "user") or config.app["proxy"]["password"] != self.dialog.get_value("proxy", "password"):
if self.is_started == True:
self.needs_restart = True
config.app["proxy"]["type"]=self.dialog.get_value("proxy", "type")
config.app["proxy"]["type"] = self.dialog.proxy.type.Selection
config.app["proxy"]["server"] = self.dialog.get_value("proxy", "server")
config.app["proxy"]["port"] = self.dialog.get_value("proxy", "port")
config.app["proxy"]["user"] = self.dialog.get_value("proxy", "user")

View File

@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from builtins import object
from wxUI.dialogs import trends
import widgetUtils
@ -10,7 +8,7 @@ class trendingTopicsController(object):
self.countries = {}
self.cities = {}
self.dialog = trends.trendingTopicsDialog()
self.information = session.twitter.get_available_trends()
self.information = session.twitter.trends_available()
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)

View File

@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from builtins import object
import wx
import webbrowser
import widgetUtils
@ -8,7 +6,8 @@ import output
from wxUI.dialogs import update_profile, show_user
import logging
log = logging.getLogger("controller.user")
from twython import TwythonError
from tweepy.error import TweepError
from sessions.twitter import utils
class profileController(object):
def __init__(self, session, user=None):
@ -25,36 +24,36 @@ class profileController(object):
else:
try:
self.get_data(screen_name=self.user)
except TwythonError as err:
if err.error_code == 404:
except TweepError as err:
if err.api_code == 50:
wx.MessageDialog(None, _(u"That user does not exist"), _(u"Error"), wx.ICON_ERROR).ShowModal()
if err.error_code == 403:
if err.api_code == 403:
wx.MessageDialog(None, _(u"User has been suspended"), _(u"Error"), wx.ICON_ERROR).ShowModal()
log.error("error %d: %s" % (err.error_code, err.msg))
log.error("error %d: %s" % (err.api_code, err.reason))
return
self.dialog = show_user.showUserProfile()
string = self.get_user_info()
self.dialog.set("text", string)
self.dialog.set_title(_(u"Information for %s") % (self.data["screen_name"]))
if self.data["url"] != None:
self.dialog.set_title(_(u"Information for %s") % (self.data.screen_name))
if self.data.url != None:
self.dialog.enable_url()
widgetUtils.connect_event(self.dialog.url, widgetUtils.BUTTON_PRESSED, self.visit_url)
if self.dialog.get_response() == widgetUtils.OK and self.user == None:
self.do_update()
def get_data(self, screen_name):
self.data = self.session.twitter.show_user(screen_name=screen_name)
self.data = self.session.twitter.get_user(screen_name=screen_name)
if screen_name != self.session.db["user_name"]:
self.friendship_status = self.session.twitter.show_friendship(source_screen_name=self.session.db["user_name"], target_screen_name=screen_name)
def fill_profile_fields(self):
self.dialog.set_name(self.data["name"])
if self.data["url"] != None:
self.dialog.set_url(self.data["url"])
if len(self.data["location"]) > 0:
self.dialog.set_location(self.data["location"])
if len(self.data["description"]) > 0:
self.dialog.set_description(self.data["description"])
self.dialog.set_name(self.data.name)
if self.data.url != None:
self.dialog.set_url(self.data.url)
if len(self.data.location) > 0:
self.dialog.set_location(self.data.location)
if len(self.data.description) > 0:
self.dialog.set_description(self.data.description)
def get_image(self):
file = self.dialog.upload_picture()
@ -84,48 +83,46 @@ class profileController(object):
if self.file != None:
try:
self.session.twitter.update_profile_image(image=self.file)
except TwythonError as e:
output.speak(u"Error %s. %s" % (e.error_code, e.msg))
except TweepError as e:
output.speak(u"Error %s. %s" % (e.api_code, e.reason))
try:
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))
except TweepError as e:
output.speak(u"Error %s. %s" % (e.api_code, e.reason))
def get_user_info(self):
string = u""
string = string + _(u"Username: @%s\n") % (self.data["screen_name"])
string = string + _(u"Name: %s\n") % (self.data["name"])
if self.data["location"] != "":
string = string + _(u"Location: %s\n") % (self.data["location"])
if self.data["url"] != None:
string = string+ _(u"URL: %s\n") % (self.data["entities"]["url"]["urls"][0]["expanded_url"])
if self.data["description"] != "":
if self.data["entities"].get("description") != None and self.data["entities"]["description"].get("urls"):
for url in self.data["entities"]["description"]["urls"]:
if url["url"] in self.data["description"]:
self.data["description"] = self.data["description"].replace(url["url"], url["expanded_url"])
string = string+ _(u"Bio: %s\n") % (self.data["description"])
if self.data["protected"] == True: protected = _(u"Yes")
string = string + _(u"Username: @%s\n") % (self.data.screen_name)
string = string + _(u"Name: %s\n") % (self.data.name)
if self.data.location != "":
string = string + _(u"Location: %s\n") % (self.data.location)
if self.data.url != None:
string = string+ _(u"URL: %s\n") % (self.data.entities["url"]["urls"][0]["expanded_url"])
if self.data.description != "":
if self.data.entities.get("description") != None and self.data.entities["description"].get("urls"):
self.data.description = utils.expand_urls(self.data.description, self.data.entities["description"])
string = string+ _(u"Bio: %s\n") % (self.data.description)
if self.data.protected == True: protected = _(u"Yes")
else: protected = _(u"No")
string = string+ _(u"Protected: %s\n") % (protected)
if hasattr(self, "friendship_status"):
relation = False
friendship = "Relationship: "
if self.friendship_status["relationship"]["target"]["followed_by"]:
friendship += _(u"You follow {0}. ").format(self.data["name"],)
if self.friendship_status[0].following:
friendship += _(u"You follow {0}. ").format(self.data.name,)
relation = True
if self.friendship_status["relationship"]["target"]["following"]:
friendship += _(u"{0} is following you.").format(self.data["name"],)
if self.friendship_status[1].following:
friendship += _(u"{0} is following you.").format(self.data.name,)
relation = True
if relation == True:
string = string+friendship+"\n"
string = string+_(u"Followers: %s\n Friends: %s\n") % (self.data["followers_count"], self.data["friends_count"])
if self.data["verified"] == True: verified = _(u"Yes")
string = string+_(u"Followers: %s\n Friends: %s\n") % (self.data.followers_count, self.data.friends_count)
if self.data.verified == True: verified = _(u"Yes")
else: verified = _(u"No")
string = string+ _(u"Verified: %s\n") % (verified)
string = string+ _(u"Tweets: %s\n") % (self.data["statuses_count"])
string = string+ _(u"Likes: %s") % (self.data["favourites_count"])
string = string+ _(u"Tweets: %s\n") % (self.data.statuses_count)
string = string+ _(u"Likes: %s") % (self.data.favourites_count)
return string
def visit_url(self, *args, **kwargs):
webbrowser.open_new_tab(self.data["url"])
webbrowser.open_new_tab(self.data.url)

View File

@ -1,12 +1,9 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from builtins import object
import re
import widgetUtils
import output
from wxUI.dialogs import userActions
from pubsub import pub
from twython import TwythonError
from tweepy.error import TweepError
from extra import autocompletionUsers
class userActionsController(object):
@ -32,51 +29,51 @@ class userActionsController(object):
def follow(self, user):
try:
self.session.twitter.create_friendship(screen_name=user )
except TwythonError as err:
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
except TweepError as err:
output.speak("Error %s: %s" % (err.api_code, err.reason), True)
def unfollow(self, user):
try:
id = self.session.twitter.destroy_friendship(screen_name=user )
except TwythonError as err:
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
except TweepError as err:
output.speak("Error %s: %s" % (err.api_code, err.reason), True)
def mute(self, user):
try:
id = self.session.twitter.create_mute(screen_name=user )
except TwythonError as err:
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
except TweepError as err:
output.speak("Error %s: %s" % (err.api_code, err.reason), True)
def unmute(self, user):
try:
id = self.session.twitter.destroy_mute(screen_name=user )
except TwythonError as err:
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
except TweepError as err:
output.speak("Error %s: %s" % (err.api_code, err.reason), True)
def report(self, user):
try:
id = self.session.twitter.report_spam(screen_name=user )
except TwythonError as err:
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
except TweepError as err:
output.speak("Error %s: %s" % (err.api_code, err.reason), True)
def block(self, user):
try:
id = self.session.twitter.create_block(screen_name=user )
except TwythonError as err:
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
except TweepError as err:
output.speak("Error %s: %s" % (err.api_code, err.reason), True)
def unblock(self, user):
try:
id = self.session.twitter.destroy_block(screen_name=user )
except TwythonError as err:
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
except TweepError as err:
output.speak("Error %s: %s" % (err.api_code, err.reason), True)
def ignore_client(self, user):
tweet = self.buffer.get_right_tweet()
if "sender" in tweet:
if hasattr(tweet, "sender"):
output.speak(_(u"You can't ignore direct messages"))
return
client = re.sub(r"(?s)<.*?>", "", tweet["source"])
client = tweet.source
if client not in self.session.settings["twitter"]["ignored_clients"]:
self.session.settings["twitter"]["ignored_clients"].append(client)
self.session.settings.write()

View File

@ -1,7 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import unicode_literals
from builtins import object
import output
from . import storage
from . import wx_menu

View File

@ -1,11 +1,6 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import unicode_literals
# -*- coding: utf-8 -*-
from builtins import object
from . import storage
import widgetUtils
from . import wx_manage
from . import storage, wx_manage
from wxUI import commonMessageDialogs
class autocompletionManage(object):
@ -32,11 +27,11 @@ class autocompletionManage(object):
if usr == False:
return
try:
data = self.session.twitter.twitter.show_user(screen_name=usr)
data = self.session.twitter.twitter.get_user(screen_name=usr)
except:
self.dialog.show_invalid_user_error()
return
self.database.set_user(data["screen_name"], data["name"], 0)
self.database.set_user(data.screen_name, data.name, 0)
self.update_list()
def remove_user(self, ev):

View File

@ -1,13 +1,9 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import unicode_literals
# -*- coding: utf-8 -*-
from builtins import object
from . import storage
import widgetUtils
import output
from . import wx_settings
from . import manage
import output
from . import storage
from mysc.thread_utils import call_threaded
class autocompletionSettings(object):
@ -30,14 +26,14 @@ class autocompletionSettings(object):
database = storage.storage(self.buffer.session.session_id)
if self.dialog.get("followers_buffer") == True:
buffer = self.window.search_buffer("followers", self.config["twitter"]["user_name"])
for i in buffer.session.db[buffer.name]["items"]:
database.set_user(i["screen_name"], i["name"], 1)
for i in buffer.session.db[buffer.name]:
database.set_user(i.screen_name, i.name, 1)
else:
database.remove_by_buffer(1)
if self.dialog.get("friends_buffer") == True:
buffer = self.window.search_buffer("friends", self.config["twitter"]["user_name"])
for i in buffer.session.db[buffer.name]["items"]:
database.set_user(i["screen_name"], i["name"], 2)
for i in buffer.session.db[buffer.name]:
database.set_user(i.screen_name, i.name, 2)
else:
database.remove_by_buffer(2)
wx_settings.show_success_dialog()
@ -52,12 +48,12 @@ def execute_at_startup(window, buffer, config):
if config["mysc"]["save_followers_in_autocompletion_db"] == True and config["other_buffers"]["show_followers"] == True:
buffer = window.search_buffer("followers", config["twitter"]["user_name"])
for i in buffer.session.db[buffer.name]:
database.set_user(i["screen_name"], i["name"], 1)
database.set_user(i.screen_name, i.name, 1)
else:
database.remove_by_buffer(1)
if config["mysc"]["save_friends_in_autocompletion_db"] == True and config["other_buffers"]["show_friends"] == True:
buffer = window.search_buffer("friends", config["twitter"]["user_name"])
for i in buffer.session.db[buffer.name]:
database.set_user(i["screen_name"], i["name"], 2)
database.set_user(i.screen_name, i.name, 2)
else:
database.remove_by_buffer(2)

View File

@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from builtins import object
import os, sqlite3, paths
class storage(object):

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import wx
import widgetUtils
from multiplatform_widgets import widgets
import application
class autocompletionManageDialog(widgetUtils.BaseDialog):
def __init__(self):
super(autocompletionManageDialog, self).__init__(parent=None, id=-1, title=_(u"Manage Autocompletion database"))

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import wx
class menu(wx.Menu):

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import wx
import widgetUtils
import application

View File

@ -1,15 +1,23 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from builtins import zip
from yandex_translate import YandexTranslate
import logging
from googletrans import Translator, LANGUAGES
log = logging.getLogger("extras.translator")
# create a single translator instance
# see https://github.com/ssut/py-googletrans/issues/234
t = None
def translate(text="", target="en"):
t = YandexTranslate("trnsl.1.1.20161012T134532Z.d01b9c75fc39aa74.7d1be75a5166a80583eeb020e10f584168da6bf7")
vars = dict(text=text, lang=target)
return t.translate(**vars)["text"][0]
global t
log.debug("Received translation request for language %s, text=%s" % (target, text))
if t == None:
t = Translator()
vars = dict(text=text, dest=target)
return t.translate(**vars).text
supported_langs = None
d = None
languages = {
"af": _(u"Afrikaans"),
"sq": _(u"Albanian"),
@ -105,11 +113,4 @@ languages = {
}
def available_languages():
global supported_langs, d
if supported_langs == None and d == None:
t = YandexTranslate("trnsl.1.1.20161012T134532Z.d01b9c75fc39aa74.7d1be75a5166a80583eeb020e10f584168da6bf7")
supported_langs = t.langs
d = []
for i in supported_langs:
d.append(languages[i])
return sorted(zip(supported_langs, d))
return dict(sorted(languages.items(), key=lambda x: x[1]))

View File

@ -16,37 +16,21 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
from __future__ import absolute_import
from __future__ import unicode_literals
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
from . import translator
import wx
from wxUI.dialogs import baseDialog
class translateDialog(baseDialog.BaseWXDialog):
def __init__(self):
languages = []
language_dict = translator.available_languages()
for k in language_dict:
languages.append(language_dict[k])
super(translateDialog, self).__init__(None, -1, title=_(u"Translate message"))
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
staticDest = wx.StaticText(panel, -1, _(u"Target language"))
self.dest_lang = wx.ComboBox(panel, -1, choices=[x[1] for x in translator.available_languages()], style = wx.CB_READONLY)
self.dest_lang = wx.ComboBox(panel, -1, choices=languages, style = wx.CB_READONLY)
self.dest_lang.SetFocus()
self.dest_lang.SetSelection(0)
listSizer = wx.BoxSizer(wx.HORIZONTAL)

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -6,15 +6,15 @@ msgid ""
msgstr ""
"Project-Id-Version: TW Blue 0.85\n"
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
"PO-Revision-Date: 2018-08-15 09:47+0400\n"
"Last-Translator: Manuel Cortez <manuel@manuelcortez.net>\n"
"PO-Revision-Date: 2020-10-23 14:30+0300\n"
"Last-Translator: Artem Plaksin <admin@maniyax.ru>\n"
"Language-Team: Alexander Jaszyn <a.jaszyn@ya.ru>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
"X-Generator: Poedit 1.5.7\n"
"X-Generator: Poedit 1.8.8\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Poedit-SourceCharset: UTF-8\n"
@ -84,24 +84,22 @@ msgid "Muted users"
msgstr "Отключенные пользователи"
#: ../src\controller\buffers\twitterBuffers.py:75
#, fuzzy
msgid "{username}'s timeline"
msgstr "Открыть ленту пользователя"
msgstr "Лента твитов {username}"
#: ../src\controller\buffers\twitterBuffers.py:77
msgid "{username}'s likes"
msgstr ""
msgstr "Понравившееся {username}"
#: ../src\controller\buffers\twitterBuffers.py:79
msgid "{username}'s followers"
msgstr ""
msgstr "Читающие {username}"
#: ../src\controller\buffers\twitterBuffers.py:81
msgid "{username}'s friends"
msgstr ""
msgstr "Список читаемых {username}"
#: ../src\controller\buffers\twitterBuffers.py:83
#, fuzzy
msgid "Unknown buffer"
msgstr "Неизвестно"
@ -119,14 +117,12 @@ msgid "Write the tweet here"
msgstr "Напишите текст твита здесь"
#: ../src\controller\buffers\twitterBuffers.py:194
#, fuzzy
msgid "New tweet in {0}"
msgstr "Новый твит"
msgstr "Новый твит в {0}"
#: ../src\controller\buffers\twitterBuffers.py:197
#, fuzzy
msgid "{0} new tweets in {1}."
msgstr "Пользователь @{0} процитировал ваш твит: {1}"
msgstr "@{0} процитировал ваш твит: {1}"
#: ../src\controller\buffers\twitterBuffers.py:232
#: ../src\controller\buffers\twitterBuffers.py:676
@ -182,7 +178,7 @@ msgstr "Профиль"
#: ../src\controller\buffers\twitterBuffers.py:634
#: ../src\controller\buffers\twitterBuffers.py:987
msgid "Opening item in web browser..."
msgstr ""
msgstr "Открыть в браузере"
#: ../src\controller\buffers\twitterBuffers.py:688
#: ../src\controller\buffers\twitterBuffers.py:855
@ -196,12 +192,10 @@ msgid "Mention"
msgstr "Упомянуть"
#: ../src\controller\buffers\twitterBuffers.py:728
#, fuzzy
msgid "{0} new direct messages."
msgstr "Новое личное сообщение"
#: ../src\controller\buffers\twitterBuffers.py:731
#, fuzzy
msgid "This action is not supported in the buffer yet."
msgstr "Это действие не поддерживается в данном буфере"
@ -210,6 +204,8 @@ msgid ""
"Getting more items cannot be done in this buffer. Use the direct messages "
"buffer instead."
msgstr ""
"Невозможно получить больше элементов в данном буфере, используйте буфер "
"личных сообщений вместо этого."
#: ../src\controller\buffers\twitterBuffers.py:983
#, fuzzy
@ -379,12 +375,11 @@ msgstr "Список уже открыт"
#: ../src\controller\mainController.py:1423
#: ../src\controller\mainController.py:1439
#, fuzzy
msgid ""
"An error happened while trying to connect to the server. Please try later."
msgstr ""
"Что-то неожиданное произошло при попытке сообщить об ошибке. Пожалуйста, "
"повторите попытку позже"
"При попытке подключиться к серверу произошла ошибка. Пожалуйста, попробуйте "
"позже."
#: ../src\controller\mainController.py:1475
msgid "The auto-reading of new tweets is enabled for this buffer"
@ -874,19 +869,19 @@ msgstr "Игнорировать"
#: ../src\extra\SpellChecker\wx_ui.py:43
msgid "I&gnore all"
msgstr "Игнорировать все"
msgstr "&Игнорировать все"
#: ../src\extra\SpellChecker\wx_ui.py:44
msgid "&Replace"
msgstr "Заменить"
msgstr "&Заменить"
#: ../src\extra\SpellChecker\wx_ui.py:45
msgid "R&eplace all"
msgstr "Заменить все"
msgstr "З&аменить все"
#: ../src\extra\SpellChecker\wx_ui.py:46
msgid "&Add to personal dictionary"
msgstr "Добавить в личный словарь"
msgstr "&Добавить в личный словарь"
#: ../src\extra\SpellChecker\wx_ui.py:79
msgid ""
@ -1587,9 +1582,8 @@ msgid "Open URL"
msgstr "Открыть ссылку"
#: ../src\keystrokeEditor\constants.py:25
#, fuzzy
msgid "View in Twitter"
msgstr "Поиск в твиттере"
msgstr "Посмотреть в Твиттере"
#: ../src\keystrokeEditor\constants.py:26
msgid "Increase volume by 5%"
@ -1693,7 +1687,7 @@ msgstr "Просмотр беседы"
#: ../src\keystrokeEditor\constants.py:51
msgid "Check and download updates"
msgstr "Проверить на наличие обновлений"
msgstr "Проверить наличие обновлений"
#: ../src\keystrokeEditor\constants.py:52
msgid ""
@ -1816,6 +1810,9 @@ msgid ""
"If you're sure that {0} isn't running, try deleting the file at {1}. If "
"you're unsure of how to do this, contact the {0} developers."
msgstr ""
"{0} уже запущен. Закройте другой экземпляр, прежде чем запускать этот. Если "
"вы уверены, что {0} не активен, попробуйте удалить файл по адресу {1}. Если "
"вы не знаете, как это сделать, обратитесь к разработчикам {0}."
#: ../src\sessionmanager\wxUI.py:8
msgid "Session manager"
@ -1920,9 +1917,8 @@ msgid "public"
msgstr "Публичный"
#: ../src\sessions\twitter\session.py:169
#, fuzzy
msgid "There are no more items to retrieve in this buffer."
msgstr "Координаты отсутствуют"
msgstr "В этом буфере больше нет элементов для извлечения."
#: ../src\sessions\twitter\session.py:215
msgid "%s failed. Reason: %s"
@ -2048,7 +2044,7 @@ msgstr "Тренды"
#: ../src\wxUI\buffers\trends.py:18
msgid "Tweet about this trend"
msgstr "Tweet о тренде"
msgstr "Твитнуть о тренде"
#: ../src\wxUI\buffers\trends.py:19 ../src\wxUI\menus.py:96
msgid "Search topic"
@ -2265,6 +2261,8 @@ msgid ""
"{0} quit unexpectedly the last time it was run. If the problem persists, "
"please report it to the {0} developers."
msgstr ""
"{0} неожиданно закончил свою работу при последнем запуске. Если проблема не "
"устранена, пожалуйста, сообщите об этом разработчикам {0}."
#: ../src\wxUI\dialogs\attach.py:9
msgid "Add an attachment"
@ -2362,6 +2360,7 @@ msgstr "Использование удлинителя твитов (может
#: ../src\wxUI\dialogs\configuration.py:48
msgid "Remember state for mention all and long tweet"
msgstr ""
"Запоминать состояние для упоминаний всех пользователей и длинных твитов"
#: ../src\wxUI\dialogs\configuration.py:51
msgid "Keymap"
@ -2413,7 +2412,7 @@ msgstr ""
#: ../src\wxUI\dialogs\configuration.py:116
msgid "Retweet mode"
msgstr "Стиль ретвита"
msgstr "Режим ретвита"
#: ../src\wxUI\dialogs\configuration.py:122
msgid "Show screen names instead of full names"
@ -2429,11 +2428,11 @@ msgstr ""
#: ../src\wxUI\dialogs\configuration.py:134
msgid "Enable automatic speech feedback"
msgstr ""
msgstr "Включить автоматический речевой вывод"
#: ../src\wxUI\dialogs\configuration.py:136
msgid "Enable automatic Braille feedback"
msgstr ""
msgstr "Включить автоматический брайлевский вывод"
#: ../src\wxUI\dialogs\configuration.py:144
msgid "Status"
@ -2515,7 +2514,7 @@ msgstr "Устройство записи"
#: ../src\wxUI\dialogs\configuration.py:299
msgid "Sound pack"
msgstr "Пакет звуков"
msgstr "Звуковая схема"
#: ../src\wxUI\dialogs\configuration.py:305
msgid "Indicate audio tweets with sound"
@ -2539,7 +2538,7 @@ msgstr "API ключ SndUp"
#: ../src\wxUI\dialogs\configuration.py:353
msgid "{0} preferences"
msgstr "Настройки {0}"
msgstr "Параметры {0}"
#: ../src\wxUI\dialogs\configuration.py:364
msgid "Proxy"
@ -2819,9 +2818,8 @@ msgid "Source: "
msgstr "Клиент"
#: ../src\wxUI\dialogs\message.py:342 ../src\wxUI\dialogs\message.py:420
#, fuzzy
msgid "Date: "
msgstr "Дата"
msgstr "Дата: "
#: ../src\wxUI\dialogs\message.py:405
msgid "View"
@ -2890,7 +2888,7 @@ msgstr "Детали"
#: ../src\wxUI\dialogs\show_user.py:16
msgid "&Go to URL"
msgstr "Перейти по ссылке"
msgstr "&Перейти по ссылке"
#: ../src\wxUI\dialogs\trends.py:12
msgid "View trending topics"
@ -3031,12 +3029,11 @@ msgstr "н&е нравится"
#: ../src\wxUI\menus.py:15 ../src\wxUI\menus.py:35 ../src\wxUI\menus.py:51
msgid "&Open URL"
msgstr "Открыть ссылку"
msgstr "&Открыть ссылку"
#: ../src\wxUI\menus.py:17 ../src\wxUI\menus.py:53 ../src\wxUI\menus.py:86
#, fuzzy
msgid "&Open in Twitter"
msgstr "Поиск в твиттере"
msgstr "Открыть в &Твиттере"
#: ../src\wxUI\menus.py:19 ../src\wxUI\menus.py:37 ../src\wxUI\menus.py:55
msgid "&Play audio"
@ -3246,7 +3243,7 @@ msgstr "Сайт {0}"
#: ../src\wxUI\view.py:77
msgid "Get soundpacks for TWBlue"
msgstr ""
msgstr "Получить звуковые схемы для TWBlue"
#: ../src\wxUI\view.py:78
msgid "About &{0}"

View File

@ -65,6 +65,7 @@ log = logging.getLogger("main")
def setup():
log.debug("Starting " + application.name + " %s" % (application.version,))
config.setup()
proxy_setup()
log.debug("Using %s %s" % (platform.system(), platform.architecture()[0]))
log.debug("Application path is %s" % (paths.app_path(),))
log.debug("config path is %s" % (paths.config_path(),))
@ -77,6 +78,7 @@ def setup():
from controller import mainController
from sessionmanager import sessionManager
app = widgetUtils.mainLoopObject()
check_pid()
if system == "Windows":
if config.app["app-settings"]["donation_dialog_displayed"] == False:
donation()
@ -90,7 +92,6 @@ def setup():
if hasattr(sm.view, "destroy"):
sm.view.destroy()
del sm
check_pid()
r = mainController.Controller()
r.view.show()
r.do_work()
@ -101,6 +102,18 @@ def setup():
GLib.idle_add(r.start)
app.run()
def proxy_setup():
if config.app["proxy"]["server"] != "" and config.app["proxy"]["type"] > 0:
log.debug("Loading proxy settings")
proxy_url = config.app["proxy"]["server"] + ":" + str(config.app["proxy"]["port"])
if config.app["proxy"]["user"] != "" and config.app["proxy"]["password"] != "":
proxy_url = config.app["proxy"]["user"] + ":" + config.app["proxy"]["password"] + "@" + proxy_url
elif config.app["proxy"]["user"] != "" and config.proxyTypes[config.app["proxy"]["type"]] in ["socks4", "socks4a"]:
proxy_url = config.app["proxy"]["user"] + "@" + proxy_url
proxy_url = config.proxyTypes[config.app["proxy"]["type"]] + "://" + proxy_url
os.environ["HTTP_PROXY"] = proxy_url
os.environ["HTTPS_PROXY"] = proxy_url
def donation():
dlg = commonMessageDialogs.donation()
if dlg == widgetUtils.YES:

View File

@ -1,21 +1,15 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from future import standard_library
standard_library.install_aliases()
import logging
log = logging.getLogger("mysc.thread_utils")
import threading
import wx
from pubsub import pub
from twython import TwythonRateLimitError
def call_threaded(func, *args, **kwargs):
#Call the given function in a daemonized thread and return the thread.
def new_func(*a, **k):
try:
func(*a, **k)
except TwythonRateLimitError:
pass
except:
log.exception("Thread %d with function %r, args of %r, and kwargs of %r failed to run." % (threading.current_thread().ident, func, a, k))
# pass
@ -23,17 +17,3 @@ def call_threaded(func, *args, **kwargs):
thread.daemon = True
thread.start()
return thread
def stream_threaded(func, *args, **kwargs):
def new_func(*a, **k):
try:
func(**k)
except Exception as msg:
log.error("Error in stream with args: %r" % (a,))
log.error(msg.message)
pub.sendMessage("stream-error", session=a[0])
thread = threading.Thread(target=new_func, args=args, kwargs=kwargs)
thread.daemon = True
thread.start()
return thread

View File

@ -1,8 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import unicode_literals
from builtins import str
from builtins import object
import shutil
import widgetUtils
import platform
@ -21,7 +17,7 @@ from sessions.twitter import session
from . import manager
import config_utils
import config
from twython.exceptions import TwythonAuthError
from tweepy.error import TweepError
log = logging.getLogger("sessionmanager.sessionManager")
class sessionManagerController(object):
@ -87,7 +83,7 @@ class sessionManagerController(object):
if i not in config.app["sessions"]["ignored_sessions"]:
try:
s.login()
except TwythonAuthError:
except TweepError:
self.show_auth_error(s.settings["twitter"]["user_name"])
continue
sessions.sessions[i] = s

View File

@ -75,7 +75,7 @@ class baseSession(object):
def shelve(self):
"""Shelve the database to allow for persistance."""
shelfname=os.path.join(paths.config_path(), str(self.session_id)+"/cache")
shelfname=os.path.join(paths.config_path(), str(self.session_id), "cache")
if self.settings["general"]["persist_size"] == 0:
if os.path.exists(shelfname+".dat"):
os.remove(shelfname+".dat")

View File

@ -20,7 +20,6 @@ import config
from .long_tweets import twishort, tweets
log = logging.getLogger("compose")
def StripChars(s):
"""Converts any html entities in s to their unicode-decoded equivalents and returns a string."""
entity_re = re.compile(r"&(#\d+|\w+);")
@ -39,129 +38,118 @@ chars = "abcdefghijklmnopqrstuvwxyz"
def compose_tweet(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")
original_date = arrow.get(tweet.created_at, locale="en")
if relative_times == True:
ts = original_date.humanize(locale=languageHandler.curLang[:2])
else:
ts = original_date.shift(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.curLang[:2])
else:
ts = tweet["created_at"]
if "message" in tweet:
ts = tweet.created_at
if hasattr(tweet, "message"):
value = "message"
elif "full_text" in tweet:
elif hasattr(tweet, "full_text"):
value = "full_text"
else:
value = "text"
if "retweeted_status" in tweet and value != "message":
text = StripChars(tweet["retweeted_status"][value])
if hasattr(tweet, "retweeted_status") and value != "message":
text = StripChars(getattr(tweet.retweeted_status, value))
else:
text = StripChars(tweet[value])
text = StripChars(getattr(tweet, value))
if show_screen_names:
user = tweet["user"]["screen_name"]
user = tweet.user.screen_name
else:
user = tweet["user"]["name"]
source = re.sub(r"(?s)<.*?>", "", tweet["source"])
if "retweeted_status" in tweet:
if ("message" in tweet) == False and tweet["retweeted_status"]["is_quote_status"] == False:
text = "RT @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], text)
elif tweet["retweeted_status"]["is_quote_status"]:
user = tweet.user.name
source = re.sub(r"(?s)<.*?>", "", tweet.source)
if hasattr(tweet, "retweeted_status"):
if (hasattr(tweet, "message")) == False and tweet.retweeted_status.is_quote_status == False:
text = "RT @%s: %s" % (tweet.retweeted_status.user.screen_name, text)
elif tweet.retweeted_status.is_quote_status:
text = "%s" % (text)
else:
text = "RT @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], text)
if ("message" in tweet) == False:
urls = utils.find_urls_in_text(text)
if "retweeted_status" in tweet:
for url in range(0, len(urls)):
try:
text = text.replace(urls[url], tweet["retweeted_status"]["entities"]["urls"][url]["expanded_url"])
except: pass
text = "RT @%s: %s" % (tweet.retweeted_status.user.screen_name, text)
if not hasattr(tweet, "message"):
if hasattr(tweet, "retweeted_status"):
text = utils.expand_urls(text, tweet.retweeted_status.entities)
else:
for url in range(0, len(urls)):
try:
text = text.replace(urls[url], tweet["entities"]["urls"][url]["expanded_url"])
except: pass
text = utils.expand_urls(text, tweet.entities)
if config.app['app-settings']['handle_longtweets']: 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).
if system == "Windows":
# Let's remove the last 3 digits in the timestamp string.
# Twitter sends their "epoch" timestamp with 3 digits for milliseconds and arrow doesn't like it.
original_date = arrow.get(int(item["created_timestamp"][:-3]))
original_date = arrow.get(int(item.created_timestamp))
if relative_times == True:
ts = original_date.humanize(locale=languageHandler.curLang[:2])
else:
ts = original_date.shift(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.curLang[:2])
else:
ts = item["created_timestamp"]
text = StripChars(item["message_create"]["message_data"]["text"])
ts = item.created_timestamp
text = StripChars(item.message_create["message_data"]["text"])
source = "DM"
sender = session.get_user(item["message_create"]["sender_id"])
if db["user_name"] == sender["screen_name"]:
sender = session.get_user(item.message_create["sender_id"])
if db["user_name"] == sender.screen_name:
if show_screen_names:
user = _(u"Dm to %s ") % (session.get_user(item["message_create"]["target"]["recipient_id"])["screen_name"])
user = _(u"Dm to %s ") % (session.get_user(item.message_create["target"]["recipient_id"]).screen_name)
else:
user = _(u"Dm to %s ") % (session.get_user(item["message_create"]["target"]["recipient_id"])["name"])
user = _(u"Dm to %s ") % (session.get_user(item.message_create["target"]["recipient_id"]).name)
else:
if show_screen_names:
user = sender["screen_name"]
user = sender.screen_name
else:
user = sender["name"]
user = 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], item["message_create"]["message_data"]["entities"]["urls"][url]["expanded_url"])
except IndexError: pass
text = utils.expand_urls(text, item.message_create["message_data"]["entities"])
return [user+", ", text, ts+", ", source]
def compose_quoted_tweet(quoted_tweet, original_tweet, show_screen_names=False, session=None):
""" It receives a tweet and returns a list with the user, text for the tweet or message, date and the client where user is."""
if "retweeted_status" in quoted_tweet:
if "full_text" in quoted_tweet["retweeted_status"]:
if hasattr(quoted_tweet, "retweeted_status"):
if hasattr(quoted_tweet.retweeted_status, "full_text"):
value = "full_text"
else:
value = "text"
text = StripChars(quoted_tweet["retweeted_status"][value])
text = StripChars(getattr(quoted_tweet.retweeted_status, value))
else:
if "full_text" in quoted_tweet:
if hasattr(quoted_tweet, "full_text"):
value = "full_text"
else:
value = "text"
text = StripChars(quoted_tweet[value])
text = StripChars(getattr(quoted_tweet, value))
if show_screen_names:
quoting_user = quoted_tweet["user"]["screen_name"]
quoting_user = quoted_tweet.user.screen_name
else:
quoting_user = quoted_tweet["user"]["name"]
source = re.sub(r"(?s)<.*?>", "", quoted_tweet["source"])
if "retweeted_status" in quoted_tweet:
text = "rt @%s: %s" % (quoted_tweet["retweeted_status"]["user"]["screen_name"], text)
quoting_user = quoted_tweet.user.name
source = quoted_tweet.source
if hasattr(quoted_tweet, "retweeted_status"):
text = "rt @%s: %s" % (quoted_tweet.retweeted_status.user.screen_name, text)
if text[-1] in chars: text=text+"."
original_user = original_tweet["user"]["screen_name"]
if "message" in original_tweet:
original_text = original_tweet["message"]
elif "full_text" in original_tweet:
original_text = StripChars(original_tweet["full_text"])
original_user = original_tweet.user.screen_name
if hasattr(original_tweet, "message"):
original_text = original_tweet.message
elif hasattr(original_tweet, "full_text"):
original_text = StripChars(original_tweet.full_text)
else:
original_text = StripChars(original_tweet["text"])
quoted_tweet["message"] = _(u"{0}. Quoted tweet from @{1}: {2}").format( text, original_user, original_text)
original_text = StripChars(original_tweet.text)
quoted_tweet.message = _(u"{0}. Quoted tweet from @{1}: {2}").format( text, original_user, original_text)
quoted_tweet = tweets.clear_url(quoted_tweet)
quoted_tweet["entities"]["urls"].extend(original_tweet["entities"]["urls"])
quoted_tweet.entities["urls"].extend(original_tweet.entities["urls"])
return quoted_tweet
def compose_followers_list(tweet, db, relative_times=True, show_screen_names=False, session=None):
if system == "Windows":
original_date = arrow.get(tweet["created_at"], "ddd MMM D H:m:s Z YYYY", locale="en")
original_date = arrow.get(tweet.created_at, locale="en")
if relative_times == True:
ts = original_date.humanize(locale=languageHandler.curLang[:2])
else:
ts = original_date.shift(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.curLang[:2])
else:
ts = tweet["created_at"]
if "status" in tweet:
if len(tweet["status"]) > 4 and system == "Windows":
original_date2 = arrow.get(tweet["status"]["created_at"], "ddd MMM D H:m:s Z YYYY", locale="en")
ts = tweet.created_at
if hasattr(tweet, "status"):
if system == "Windows":
original_date2 = arrow.get(tweet.status.created_at, locale="en")
if relative_times:
ts2 = original_date2.humanize(locale=languageHandler.curLang[:2])
else:
@ -170,14 +158,14 @@ def compose_followers_list(tweet, db, relative_times=True, show_screen_names=Fal
ts2 = _("Unavailable")
else:
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)]
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_list(list):
name = list["name"]
if list["description"] == None: description = _(u"No description available")
else: description = list["description"]
user = list["user"]["name"]
members = str(list["member_count"])
if list["mode"] == "private": status = _(u"private")
name = list.name
if list.description == None: description = _(u"No description available")
else: description = list.description
user = list.user.name
members = str(list.member_count)
if list.mode == "private": status = _(u"private")
else: status = _(u"public")
return [name, description, user, members, status]

View File

@ -23,30 +23,30 @@ 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 "quoted_status_id" in tweet and "quoted_status" in tweet:
return tweet["quoted_status_id"]
elif "retweeted_status" in tweet and "quoted_status_id" in tweet["retweeted_status"] and "quoted_status" in tweet["retweeted_status"]:
return tweet["retweeted_status"]["quoted_status_id"]
if hasattr(tweet, "quoted_status_id") and hasattr(tweet, "quoted_status"):
return tweet.quoted_status_id
elif hasattr(tweet, "retweeted_status") and hasattr(tweet.retweeted_status, "quoted_status_id") and hasattr(tweet.retweeted_status, "quoted_status"):
return tweet.retweeted_status.quoted_status_id
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 "retweeted_status" in tweet:
if "full_text" in tweet["retweeted_status"]:
if hasattr(tweet, "retweeted_status"):
if hasattr(tweet.retweeted_status, "full_text"):
value = "full_text"
else:
value = "text"
urls = utils.find_urls_in_text(tweet["retweeted_status"][value])
try: tweet["message"] = tweet["message"].replace(urls[-1], "")
urls = utils.find_urls_in_text(getattr(tweet.retweeted_status, value))
try: tweet.message = tweet.message.replace(urls[-1], "")
except IndexError: pass
else:
if "full_text" in tweet:
if hasattr(tweet, "full_text"):
value = "full_text"
else:
value = "text"
urls = utils.find_urls_in_text(tweet[value])
try: tweet["message"] = tweet["message"].replace(urls[-1], "")
urls = utils.find_urls_in_text(getattr(tweet, value))
try: tweet.message = tweet.message.replace(urls[-1], "")
except IndexError: pass
return tweet

View File

@ -40,21 +40,21 @@ 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"])):
for url in range(0, len(tweet.entities["urls"])):
try:
if tweet["entities"]["urls"][url] != None and "twishort.com" in tweet["entities"]["urls"][url]["expanded_url"]:
long = get_twishort_uri(tweet["entities"]["urls"][url]["expanded_url"])
if tweet.entities["urls"][url] != None and "twishort.com" in tweet.entities["urls"][url]["expanded_url"]:
long = get_twishort_uri(tweet.entities["urls"][url]["expanded_url"])
except IndexError:
pass
# sometimes Twitter returns URL's with None objects, so let's take it.
# see https://github.com/manuelcortez/TWBlue/issues/103
except TypeError:
pass
if long == False and "retweeted_status" in tweet:
for url in range(0, len(tweet["retweeted_status"]["entities"]["urls"])):
if long == False and hasattr(tweet, "retweeted_status"):
for url in range(0, len(tweet.retweeted_status.entities["urls"])):
try:
if tweet["retweeted_status"]["entities"]["urls"][url] != None and "twishort.com" in tweet["retweeted_status"]["entities"]["urls"][url]["expanded_url"]:
long = get_twishort_uri(tweet["retweeted_status"]["entities"]["urls"][url]["expanded_url"])
if tweet.retweeted_status.entities["urls"][url] != None and "twishort.com" in tweet.retweeted_status.entities["urls"][url]["expanded_url"]:
long = get_twishort_uri(tweet.retweeted_status.entities["urls"][url]["expanded_url"])
except IndexError:
pass
except TypeError:

View File

@ -1,8 +1,5 @@
# -*- coding: utf-8 -*-
""" This is the main session needed to access all Twitter Features."""
from __future__ import absolute_import
from __future__ import unicode_literals
from builtins import range
import os
import time
import logging
@ -12,7 +9,9 @@ import config
import output
import application
from pubsub import pub
from twython import Twython, TwythonError, TwythonRateLimitError, TwythonAuthError
import tweepy
from tweepy.error import TweepError
from tweepy.models import User as UserModel
from mysc.thread_utils import call_threaded
from keys import keyring
from sessions import base
@ -31,6 +30,8 @@ class Session(base.baseSession):
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"""
if name == "direct_messages":
return self.order_direct_messages(data)
num = 0
last_id = None
if (name in self.db) == False:
@ -39,43 +40,38 @@ class Session(base.baseSession):
self.db["users"] = {}
if ignore_older and len(self.db[name]) > 0:
if self.settings["general"]["reverse_timelines"] == False:
last_id = self.db[name][0]["id"]
last_id = self.db[name][0].id
else:
last_id = self.db[name][-1]["id"]
last_id = self.db[name][-1].id
for i in data:
if ignore_older and last_id != None:
if i["id"] < last_id:
log.error("Ignoring an older tweet... Last id: {0}, tweet id: {1}".format(last_id, i["id"]))
if i.id < last_id:
log.error("Ignoring an older tweet... Last id: {0}, tweet id: {1}".format(last_id, i.id))
continue
if utils.find_item(i["id"], self.db[name]) == None and utils.is_allowed(i, self.settings, name) == True:
if utils.find_item(i.id, self.db[name]) == None and utils.is_allowed(i, self.settings, name) == True:
i = self.check_quoted_status(i)
i = self.check_long_tweet(i)
if i == False: continue
if self.settings["general"]["reverse_timelines"] == False: self.db[name].append(i)
else: self.db[name].insert(0, i)
num = num+1
if ("user" in i) == True:
if (i["user"]["id"] in self.db["users"]) == False:
self.db["users"][i["user"]["id"]] = i["user"]
if hasattr(i, "user"):
if (i.user.id in self.db["users"]) == False:
self.db["users"][i.user.id] = i.user
return num
def order_cursored_buffer(self, name, data):
def order_people(self, name, data):
""" 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 (name in self.db) == False:
self.db[name] = {}
self.db[name]["items"] = []
self.db[name] = []
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)
else: self.db[name]["items"].insert(0, i)
if utils.find_item(i.id, self.db[name]) == None:
if self.settings["general"]["reverse_timelines"] == False: self.db[name].append(i)
else: self.db[name].insert(0, i)
num = num+1
return num
@ -86,24 +82,27 @@ class Session(base.baseSession):
incoming = 0
sent = 0
if ("direct_messages" in self.db) == False:
self.db["direct_messages"] = {}
self.db["direct_messages"]["items"] = []
self.db["direct_messages"] = []
for i in data:
if i["message_create"]["sender_id"] == self.db["user_id"]:
if "sent_direct_messages" in self.db and utils.find_item(i["id"], self.db["sent_direct_messages"]["items"]) == None:
if self.settings["general"]["reverse_timelines"] == False: self.db["sent_direct_messages"]["items"].append(i)
else: self.db["sent_direct_messages"]["items"].insert(0, i)
# Twitter returns sender_id as str, which must be converted to int in order to match to our user_id object.
if int(i.message_create["sender_id"]) == self.db["user_id"]:
if "sent_direct_messages" in self.db and utils.find_item(i.id, self.db["sent_direct_messages"]) == None:
if self.settings["general"]["reverse_timelines"] == False: self.db["sent_direct_messages"].append(i)
else: self.db["sent_direct_messages"].insert(0, i)
sent = sent+1
else:
if utils.find_item(i["id"], self.db["direct_messages"]["items"]) == None:
if self.settings["general"]["reverse_timelines"] == False: self.db["direct_messages"]["items"].append(i)
else: self.db["direct_messages"]["items"].insert(0, i)
if utils.find_item(i.id, self.db["direct_messages"]) == None:
if self.settings["general"]["reverse_timelines"] == False: self.db["direct_messages"].append(i)
else: self.db["direct_messages"].insert(0, i)
incoming = incoming+1
pub.sendMessage("sent-dms-updated", total=sent, account=self.db["user_name"])
return incoming
def __init__(self, *args, **kwargs):
super(Session, self).__init__(*args, **kwargs)
# Adds here the optional cursors objects.
cursors = dict(direct_messages=-1)
self.db["cursors"] = cursors
self.reconnection_function_active = False
self.counter = 0
self.lists = []
@ -115,7 +114,9 @@ class Session(base.baseSession):
if self.settings["twitter"]["user_key"] != None and self.settings["twitter"]["user_secret"] != None:
try:
log.debug("Logging in to twitter...")
self.twitter = Twython(keyring.get("api_key"), keyring.get("api_secret"), self.settings["twitter"]["user_key"], self.settings["twitter"]["user_secret"])
self.auth = tweepy.OAuthHandler(keyring.get("api_key"), keyring.get("api_secret"))
self.auth.set_access_token(self.settings["twitter"]["user_key"], self.settings["twitter"]["user_secret"])
self.twitter = tweepy.API(self.auth)
if verify_credentials == True:
self.credentials = self.twitter.verify_credentials()
self.logged = True
@ -134,19 +135,18 @@ class Session(base.baseSession):
if self.logged == True:
raise Exceptions.AlreadyAuthorisedError("The authorisation process is not needed at this time.")
else:
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.auth = tweepy.OAuthHandler(keyring.get("api_key"), keyring.get("api_secret"))
redirect_url = self.auth.get_authorization_url()
webbrowser.open_new_tab(redirect_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.auth.get_access_token(pincode)
self.settings["twitter"]["user_key"] = self.auth.access_token
self.settings["twitter"]["user_secret"] = self.auth.access_token_secret
self.settings.write()
del self.auth
@ -207,14 +207,14 @@ class Session(base.baseSession):
try:
val = getattr(self.twitter, call_name)(*args, **kwargs)
finished = True
except TwythonError as e:
output.speak(e.msg)
except TweepError as e:
output.speak(e.reason)
val = None
if e.error_code != 403 and e.error_code != 404:
tries = tries+1
time.sleep(5)
elif report_failure and hasattr(e, 'message'):
output.speak(_("%s failed. Reason: %s") % (action, e.msg))
elif report_failure and hasattr(e, 'reason'):
output.speak(_("%s failed. Reason: %s") % (action, e.reason))
finished = True
# except:
# tries = tries + 1
@ -227,15 +227,15 @@ class Session(base.baseSession):
def search(self, name, *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"]
tl.reverse()
return tl
# @_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.
args and kwargs are passed directly to the Twython function."""
tl = self.call_paged("get_favorites", *args, **kwargs)
tl = self.call_paged("favorites", *args, **kwargs)
return self.order_buffer(name, tl)
def call_paged(self, update_function, *args, **kwargs):
@ -249,8 +249,8 @@ class Session(base.baseSession):
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"]
if i == 0: max_id = results[-1].id
else: max_id = results[0].id
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()
@ -259,11 +259,11 @@ class Session(base.baseSession):
# @_require_login
def get_user_info(self):
""" Retrieves some information required by TWBlue for setup."""
f = self.twitter.get_account_settings()
f = self.twitter.get_settings()
sn = f["screen_name"]
self.settings["twitter"]["user_name"] = sn
self.db["user_name"] = sn
self.db["user_id"] = self.twitter.show_user(screen_name=sn)["id_str"]
self.db["user_id"] = self.twitter.get_user(screen_name=sn).id
try:
self.db["utc_offset"] = f["time_zone"]["utc_offset"]
except KeyError:
@ -271,7 +271,7 @@ class Session(base.baseSession):
# 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.get_supported_languages()
application.supported_languages = self.twitter.supported_languages()
self.get_lists()
self.get_muted_users()
self.settings.write()
@ -279,12 +279,12 @@ class Session(base.baseSession):
# @_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.show_lists(reverse=True)
self.db["lists"] = self.twitter.lists_all(reverse=True)
# @_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.mutes_ids()
# @_require_login
def get_stream(self, name, function, *args, **kwargs):
@ -355,32 +355,25 @@ class Session(base.baseSession):
def get_quoted_tweet(self, tweet):
""" Process a tweet and extract all information related to the quote. """
quoted_tweet = tweet
if "full_text" in tweet:
if hasattr(tweet, "full_text"):
value = "full_text"
else:
value = "text"
urls = utils.find_urls_in_text(quoted_tweet[value])
for url in range(0, len(urls)):
try: quoted_tweet[value] = quoted_tweet[value].replace(urls[url], quoted_tweet["entities"]["urls"][url]["expanded_url"])
except IndexError: pass
if "quoted_status" in quoted_tweet:
original_tweet = quoted_tweet["quoted_status"]
elif "retweeted_status" in quoted_tweet and "quoted_status" in quoted_tweet["retweeted_status"]:
original_tweet = quoted_tweet["retweeted_status"]["quoted_status"]
setattr(quoted_tweet, value, utils.expand_urls(getattr(quoted_tweet, value), quoted_tweet.entities))
if quoted_tweet.is_quote_status == True and hasattr(quoted_tweet, "quoted_status"):
original_tweet = quoted_tweet.quoted_status
elif hasattr(quoted_tweet, "retweeted_status") and quoted_tweet.retweeted_status.is_quote_status == True and hasattr(quoted_tweet.retweeted_status, "quoted_status"):
original_tweet = quoted_tweet.retweeted_status.quoted_status
else:
return quoted_tweet
original_tweet = self.check_long_tweet(original_tweet)
if "full_text" in original_tweet:
if hasattr(original_tweet, "full_text"):
value = "full_text"
elif "message" in original_tweet:
elif hasattr(original_tweet, "message"):
value = "message"
else:
value = "text"
urls = utils.find_urls_in_text(original_tweet[value])
for url in range(0, len(urls)):
try: original_tweet[value] = original_tweet[value].replace(urls[url], original_tweet["entities"]["urls"][url]["expanded_url"])
except IndexError: pass
setattr(original_tweet, value, utils.expand_urls(getattr(original_tweet, value), original_tweet.entities))
return compose.compose_quoted_tweet(quoted_tweet, original_tweet)
def check_long_tweet(self, tweet):
@ -390,36 +383,39 @@ class Session(base.baseSession):
long = twishort.is_long(tweet)
if long != False and config.app["app-settings"]["handle_longtweets"]:
message = twishort.get_full_text(long)
if "quoted_status" in tweet:
tweet["quoted_status"]["message"] = message
if tweet["quoted_status"]["message"] == False: return False
tweet["quoted_status"]["twishort"] = True
for i in tweet["quoted_status"]["entities"]["user_mentions"]:
if "@%s" % (i["screen_name"]) not in tweet["quoted_status"]["message"] and i["screen_name"] != tweet["user"]["screen_name"]:
if "retweeted_status" in tweet["quoted_status"] and tweet["retweeted_status"]["user"]["screen_name"] == i["screen_name"]:
if hasattr(tweet, "quoted_status"):
tweet.quoted_status.message = message
if tweet.quoted_status.message == False: return False
tweet.quoted_status.twishort = True
for i in tweet.quoted_status.entities["user_mentions"]:
if "@%s" % (i["screen_name"]) not in tweet.quoted_status.message and i["screen_name"] != tweet.user.screen_name:
if hasattr(tweet.quoted_status, "retweeted_status") and tweet.retweeted_status.user.screen_name == i["screen_name"]:
continue
tweet["quoted_status"]["message"] = u"@%s %s" % (i["screen_name"], tweet["message"])
tweet.quoted_status.message = u"@%s %s" % (i["screen_name"], tweet.message)
else:
tweet["message"] = message
if tweet["message"] == False: return False
tweet["twishort"] = True
for i in tweet["entities"]["user_mentions"]:
if "@%s" % (i["screen_name"]) not in tweet["message"] and i["screen_name"] != tweet["user"]["screen_name"]:
if "retweeted_status" in tweet and tweet["retweeted_status"]["user"]["screen_name"] == i["screen_name"]:
tweet.message = message
if tweet.message == False: return False
tweet.twishort = True
for i in tweet.entities["user_mentions"]:
if "@%s" % (i["screen_name"]) not in tweet.message and i["screen_name"] != tweet.user.screen_name:
if hasattr(tweet, "retweeted_status") and tweet.retweeted_status.user.screen_name == i["screen_name"]:
continue
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."""
returns a tweepy user object."""
if ("users" in self.db) == False or (id in self.db["users"]) == False:
try:
user = self.twitter.show_user(id=id)
except TwythonError:
user = dict(screen_name="deleted_account", name="Deleted account")
return user
self.db["users"][user["id_str"]] = user
user = self.twitter.get_user(id=id)
except TweepError as err:
user = UserModel(None)
user.screen_name = "deleted_user"
user.id = id
user.name = _("Deleted account")
user.id_str = id
self.db["users"][user.id_str] = user
return user
else:
return self.db["users"][id]
@ -434,8 +430,24 @@ class Session(base.baseSession):
return user["id_str"]
else:
for i in list(self.db["users"].keys()):
if self.db["users"][i]["screen_name"] == screen_name:
return self.db["users"][i]["id_str"]
if self.db["users"][i].screen_name == screen_name:
return self.db["users"][i].id_str
user = utils.if_user_exists(self.twitter, screen_name)
self.db["users"][user["id_str"]] = user
return user["id_str"]
self.db["users"][user.id_str] = user
return user.id_str
def save_users(self, user_ids):
""" Adds all new users to the users database. """
if len(user_ids) == 0:
return
log.debug("Received %d user IDS to be added in the database." % (len(user_ids)))
users_to_retrieve = [user_id for user_id in user_ids if user_id not in self.db["users"]]
# Remove duplicates
users_to_retrieve = list(dict.fromkeys(users_to_retrieve))
if len(users_to_retrieve) == 0:
return
log.debug("TWBlue will get %d new users from Twitter." % (len(users_to_retrieve)))
users = self.twitter.lookup_users(user_ids=users_to_retrieve, tweet_mode="extended")
for user in users:
self.db["users"][user.id_str] = user
log.debug("Added %d new users" % (len(users)))

View File

@ -1,16 +1,12 @@
# -*- coding: utf-8 -*-
from __future__ import print_function
from __future__ import unicode_literals
from builtins import str
from builtins import range
import url_shortener, re
import output
from twython import TwythonError
import config
import logging
import requests
import time
import sound
from tweepy.error import TweepError
log = logging.getLogger("twitter.utils")
""" Some utilities for the twitter interface."""
@ -28,35 +24,35 @@ def find_urls_in_text(text):
def find_urls (tweet):
urls = []
# Let's add URLS from tweet entities.
if "message_create" in tweet:
entities = tweet["message_create"]["message_data"]["entities"]
if hasattr(tweet, "message_create"):
entities = tweet.message_create["message_data"]["entities"]
else:
entities = tweet["entities"]
entities = tweet.entities
for i in entities["urls"]:
if i["expanded_url"] not in urls:
urls.append(i["expanded_url"])
if "quoted_status" in tweet:
for i in tweet["quoted_status"]["entities"]["urls"]:
if hasattr(tweet, "quoted_status"):
for i in tweet.quoted_status.entities["urls"]:
if i["expanded_url"] not in urls:
urls.append(i["expanded_url"])
if "retweeted_status" in tweet:
for i in tweet["retweeted_status"]["entities"]["urls"]:
if hasattr(tweet, "retweeted_status"):
for i in tweet.retweeted_status.entities["urls"]:
if i["expanded_url"] not in urls:
urls.append(i["expanded_url"])
if "quoted_status" in tweet["retweeted_status"]:
for i in tweet["retweeted_status"]["quoted_status"]["entities"]["urls"]:
if hasattr(tweet["retweeted_status"], "quoted_status"):
for i in tweet.retweeted_status.quoted_status.entities["urls"]:
if i["expanded_url"] not in urls:
urls.append(i["expanded_url"])
if "message" in tweet:
if hasattr(tweet, "message"):
i = "message"
elif "full_text" in tweet:
elif hasattr(tweet, "full_text"):
i = "full_text"
else:
i = "text"
if "message_create" in tweet:
extracted_urls = find_urls_in_text(tweet["message_create"]["message_data"]["text"])
if hasattr(tweet, "message_create"):
extracted_urls = find_urls_in_text(tweet.message_create["message_data"]["text"])
else:
extracted_urls = find_urls_in_text(tweet[i])
extracted_urls = find_urls_in_text(getattr(tweet, i))
# Don't include t.co links (mostly they are photos or shortened versions of already added URLS).
for i in extracted_urls:
if i not in urls and "https://t.co" not in i:
@ -65,124 +61,103 @@ def find_urls (tweet):
def find_item(id, listItem):
for i in range(0, len(listItem)):
if listItem[i]["id"] == id: return i
if listItem[i].id == id: return i
return None
def find_list(name, lists):
for i in range(0, len(lists)):
if lists[i]["name"] == name: return lists[i]["id"]
def find_previous_reply(id, listItem):
for i in range(0, len(listItem)):
if listItem[i]["id_str"] == str(id): return i
return None
def find_next_reply(id, listItem):
for i in range(0, len(listItem)):
if listItem[i]["in_reply_to_status_id_str"] == str(id): return i
return None
if lists[i].name == name: return lists[i].id
def is_audio(tweet):
try:
if len(find_urls(tweet)) < 1:
return False
if "message_create" in tweet:
entities = tweet["message_create"]["message_data"]["entities"]
if hasattr(tweet, "message_create"):
entities = tweet.message_create["message_data"]["entities"]
else:
entities = tweet["entities"]
entities = tweet.entities
if len(entities["hashtags"]) > 0:
for i in entities["hashtags"]:
if i["text"] == "audio":
return True
except IndexError:
print(tweet["entities"]["hashtags"])
print(tweet.entities["hashtags"])
log.exception("Exception while executing is_audio hashtag algorithm")
def is_geocoded(tweet):
if "coordinates" in tweet and tweet["coordinates"] != None:
if hasattr(tweet, "coordinates") and tweet.coordinates != None:
return True
def is_media(tweet):
if "message_create" in tweet:
entities = tweet["message_create"]["message_data"]["entities"]
if hasattr(tweet, "message_create"):
entities = tweet.message_create["message_data"]["entities"]
else:
entities = tweet["entities"]
if ("media" in entities) == False:
entities = tweet.entities
if entities.get("media") == None:
return False
for i in entities["media"]:
if "type" in i and i["type"] == "photo":
if i.get("type") != None and i.get("type") == "photo":
return True
return False
def get_all_mentioned(tweet, conf, field="screen_name"):
""" Gets all users that has been mentioned."""
""" Gets all users that have been mentioned."""
results = []
for i in tweet["entities"]["user_mentions"]:
if i["screen_name"] != conf["user_name"] and i["screen_name"] != tweet["user"]["screen_name"]:
if i[field] not in results:
results.append(i[field])
for i in tweet.entities["user_mentions"]:
if i["screen_name"] != conf["user_name"] and i["screen_name"] != tweet.user.screen_name:
if i.get(field) not in results:
results.append(i.get(field))
return results
def get_all_users(tweet, conf):
string = []
if "retweeted_status" in tweet:
string.append(tweet["user"]["screen_name"])
tweet = tweet["retweeted_status"]
if "sender" in tweet:
string.append(tweet["sender"]["screen_name"])
if hasattr(tweet, "retweeted_status"):
string.append(tweet.user.screen_name)
tweet = tweet.retweeted_status
if hasattr(tweet, "sender"):
string.append(tweet.sender.screen_name)
else:
if tweet["user"]["screen_name"] != conf["user_name"]:
string.append(tweet["user"]["screen_name"])
for i in tweet["entities"]["user_mentions"]:
if i["screen_name"] != conf["user_name"] and i["screen_name"] != tweet["user"]["screen_name"]:
if tweet.user.screen_name != conf["user_name"]:
string.append(tweet.user.screen_name)
for i in tweet.entities["user_mentions"]:
if i["screen_name"] != conf["user_name"] and i["screen_name"] != tweet.user.screen_name:
if i["screen_name"] not in string:
string.append(i["screen_name"])
if len(string) == 0:
string.append(tweet["user"]["screen_name"])
string.append(tweet.user.screen_name)
return string
def if_user_exists(twitter, user):
try:
data = twitter.show_user(screen_name=user)
data = twitter.get_user(screen_name=user)
return data
except TwythonError as err:
if err.error_code == 404:
except TweepError as err:
if err.api_code == 50:
return None
else:
return user
def api_call(parent=None, call_name=None, preexec_message="", success="", success_snd="", *args, **kwargs):
if preexec_message:
output.speak(preexec_message, True)
try:
val = getattr(parent.twitter.twitter, call_name)(*args, **kwargs)
output.speak(success)
parent.parent.sound.play(success_snd)
except TwythonError as e:
output.speak("Error %s: %s" % (e.error_code, e.msg), True)
parent.parent.sound.play("error.ogg")
return val
def is_allowed(tweet, settings, buffer_name):
clients = settings["twitter"]["ignored_clients"]
if "sender" in tweet: return True
if hasattr(tweet, "sender"): return True
allowed = True
tweet_data = {}
if "retweeted_status" in tweet:
if hasattr(tweet, "retweeted_status"):
tweet_data["retweet"] = True
if tweet["in_reply_to_status_id_str"] != None:
if tweet.in_reply_to_status_id_str != None:
tweet_data["reply"] = True
if "quoted_status" in tweet:
if hasattr(tweet, "quoted_status"):
tweet_data["quote"] = True
if "retweeted_status" in tweet: tweet = tweet["retweeted_status"]
source = re.sub(r"(?s)<.*?>", "", tweet["source"])
if hasattr(tweet, "retweeted_status"):
tweet = tweet.retweeted_status
source = tweet.source
for i in clients:
if i.lower() == source.lower():
return False
return filter_tweet(tweet, tweet_data, settings, buffer_name)
def filter_tweet(tweet, tweet_data, settings, buffer_name):
if "full_text" in tweet:
if hasattr(tweet, "full_text"):
value = "full_text"
else:
value = "text"
@ -210,24 +185,32 @@ def filter_tweet(tweet, tweet_data, settings, buffer_name):
if allow_replies == "False" and "reply" in tweet_data:
return False
if word != "" and settings["filters"][i]["if_word_exists"]:
if word in tweet[value]:
if word in getattr(tweet, value):
return False
elif word != "" and settings["filters"][i]["if_word_exists"] == False:
if word not in tweet[value]:
if word not in getattr(tweet, value):
return False
if settings["filters"][i]["in_lang"] == "True":
if tweet["lang"] not in settings["filters"][i]["languages"]:
if getattr(tweet, lang) not in settings["filters"][i]["languages"]:
return False
elif settings["filters"][i]["in_lang"] == "False":
if tweet["lang"] in settings["filters"][i]["languages"]:
if tweet.lang in settings["filters"][i]["languages"]:
return False
return True
def twitter_error(error):
if error.error_code == 403:
if error.api_code == 179:
msg = _(u"Sorry, you are not authorised to see this status.")
elif error.error_code == 404:
elif error.api_code == 144:
msg = _(u"No status found with that ID")
else:
msg = _(u"Error code {0}").format(error.error_code,)
msg = _(u"Error code {0}").format(error.api_code,)
output.speak(msg)
def expand_urls(text, entities):
""" Expand all URLS present in text with information found in entities"""
urls = find_urls_in_text(text)
for url in entities["urls"]:
if url["url"] in text:
text = text.replace(url["url"], url["expanded_url"])
return text

View File

@ -41,7 +41,7 @@ class attachDialog(widgetUtils.BaseDialog):
return (openFileDialog.GetPath(), dsc)
def ask_description(self):
dlg = wx.TextEntryDialog(self, _(u"please provide a description"), _(u"Description"), defaultValue="")
dlg = wx.TextEntryDialog(self, _(u"please provide a description"), _(u"Description"))
dlg.ShowModal()
result = dlg.GetValue()
dlg.Destroy()

View File

@ -79,7 +79,7 @@ class proxy(wx.Panel, baseDialog.BaseWXDialog):
serverBox.Add(self.server, 0, wx.ALL, 5)
sizer.Add(serverBox, 0, wx.ALL, 5)
lbl = wx.StaticText(self, wx.ID_ANY, _(u"Port: "))
self.port = wx.TextCtrl(self, wx.ID_ANY)
self.port = wx.SpinCtrl(self, wx.ID_ANY, min=1, max=65535)
portBox = wx.BoxSizer(wx.HORIZONTAL)
portBox.Add(lbl, 0, wx.ALL, 5)
portBox.Add(self.port, 0, wx.ALL, 5)

View File

@ -94,10 +94,10 @@ class editListDialog(createListDialog):
def __init__(self, list, *args, **kwargs):
super(editListDialog, self).__init__(*args, **kwargs)
self.SetTitle(_(u"Editing the list %s") % (list["name"]))
self.name.ChangeValue(list["name"])
self.description.ChangeValue(list["description"])
if list["mode"] == "public":
self.SetTitle(_(u"Editing the list %s") % (list.name))
self.name.ChangeValue(list.name)
self.description.ChangeValue(list.description)
if list.mode == "public":
self.public.SetValue(True)
else:
self.private.SetValue(True)

View File

@ -221,7 +221,7 @@ class dm(textLimited):
def __init__(self, title, message, users, *args, **kwargs):
super(dm, self).__init__()
self.createControls(message, title, users)
self.createControls(title, message, users)
# self.onTimer(wx.EVT_CHAR_HOOK)
# self.SetClientSize(self.mainBox.CalcMin())

View File

@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import unicode_literals
import widgetUtils
from . import baseDialog
import wx
@ -14,6 +12,7 @@ class searchDialog(baseDialog.BaseWXDialog):
self.SetTitle(_(u"Search on Twitter"))
label = wx.StaticText(panel, -1, _(u"&Search"))
self.term = wx.TextCtrl(panel, -1, value)
self.term.SetFocus()
dc = wx.WindowDC(self.term)
dc.SetFont(self.term.GetFont())
self.term.SetSize(dc.GetTextExtent("0"*40))

View File

@ -1,7 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import unicode_literals
# -*- coding: utf-8 -*-
from . import baseDialog
import wx
@ -11,8 +8,7 @@ class trendingTopicsDialog(baseDialog.BaseWXDialog):
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
self.SetTitle(_(u"View trending topics"))
label = wx.StaticText(panel, -1, _(u"Trending topics by"))
sizer.Add(label, 0, wx.ALL, 5)
label = wx.StaticText(panel, wx.NewId(), _(u"Trending topics by"))
self.country = wx.RadioButton(panel, -1, _(u"Country"), style=wx.RB_GROUP)
self.city = wx.RadioButton(panel, -1, _(u"City"))
radioSizer = wx.BoxSizer(wx.HORIZONTAL)

View File

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

@ -1 +1 @@
Subproject commit b6000a464758d7d09917e05f98ccd67e8d6a6c8a
Subproject commit 27d860885f8f3bf9246364f69fc66d79b7412680