Sync upstream.

This commit is contained in:
Bill Dengler
2017-10-15 22:16:18 +00:00
36 changed files with 361 additions and 187 deletions

View File

@@ -2,7 +2,7 @@
name = 'TWBlue'
snapshot = False
if snapshot == False:
version = "0.91"
version = "0.92"
update_url = 'http://twblue.es/updates/twblue_ngen.json'
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/stable.json'
else:

View File

@@ -28,21 +28,5 @@ def convert_soundcloud (url):
else:
raise TypeError('%r is not streamable' % url)
@matches_url('http://twup.me')
def convert_twup(url):
result = re.match("^http://twup.me/(?P<audio_id>[A-Za-z0-9]+/?)$", url, re.I)
if not result or result.group("audio_id") is None:
raise TypeError('%r is not a valid URL' % url)
audio_id = result.group("audio_id")
return 'http://twup.me/%s' % audio_id
#@matches_url('http://sndup.net')
#def convert_sndup(url):
# result = re.match("^http://sndup.net/(?P<audio_id>[a-z0-9]+/?)(|d|l|a)/?$", url, re.I)
# if not result or result.group("audio_id") is None:
# raise TypeError('%r is not a valid URL' % url)
# audio_id = result.group("audio_id")
# return 'http://sndup.net/%s/a' % audio_id
def convert_generic_audio(url):
return url

View File

@@ -157,7 +157,7 @@ class bufferController(object):
for i in attachments:
photo = open(i["file"], "rb")
img = self.session.twitter.twitter.upload_media(media=photo)
self.session.twitter.twitter.set_description(media_id=img["media_id"], alt_text=dict(text=i["description"]))
self.session.twitter.twitter.create_metadata(media_id=img["media_id"], alt_text=dict(text=i["description"]))
media_ids.append(img["media_id"])
self.session.twitter.twitter.update_status(status=text, media_ids=media_ids)
@@ -988,7 +988,7 @@ class searchBufferController(baseBufferController):
# return None
num = self.session.order_buffer(self.name, val)
self.put_items_on_list(num)
if num > 0:
if num > 0 and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"]:
self.session.sound.play("search_updated.ogg")
return num
@@ -1068,7 +1068,7 @@ class searchPeopleBufferController(peopleBufferController):
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:
if number_of_items > 0 and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"]:
self.session.sound.play("search_updated.ogg")
return number_of_items
@@ -1148,7 +1148,8 @@ class trendsBufferController(bufferController):
self.name_ = data[0]["locations"][0]["name"]
self.trends = data[0]["trends"]
self.put_items_on_the_list()
self.session.sound.play(self.sound)
if self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"]:
self.session.sound.play(self.sound)
def put_items_on_the_list(self):
selected_item = self.buffer.list.get_selected()
@@ -1270,7 +1271,7 @@ class conversationBufferController(searchBufferController):
number_of_items = self.session.order_buffer(self.name, self.statuses)
log.debug("Number of items retrieved: %d" % (number_of_items,))
self.put_items_on_list(number_of_items)
if number_of_items > 0:
if number_of_items > 0 and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"]:
self.session.sound.play("search_updated.ogg")
return number_of_items

View File

@@ -477,12 +477,11 @@ class Controller(object):
output.speak(_(u"Empty buffer."), True)
return
start = page.buffer.list.get_selected()
for i in xrange(start,count):
page.buffer.list.select_item(i)
if string.lower() in page.get_message().lower():
for i in xrange(start, count):
if string.lower() in page.buffer.list.get_text_column(i, 1).lower():
page.buffer.list.select_item(i)
return output.speak(page.get_message(), True)
output.speak(_(u"{0} not found.").format(string,), True)
page.buffer.list.select_item(start)
def seekLeft(self, *args, **kwargs):
try:
@@ -931,8 +930,8 @@ class Controller(object):
self.view.insert_buffer(buffer.buffer, name=_(u"Trending topics for %s") % (trends.get_string()), pos=pos)
self.buffers.append(buffer)
buffer.start_stream()
timer = RepeatingTimer(300, buffer.start_stream)
timer.start()
buffer.timer = RepeatingTimer(300, buffer.start_stream)
buffer.timer.start()
buffer.session.settings["other_buffers"]["trending_topic_buffers"].append(woeid)
buffer.session.settings.write()
@@ -987,9 +986,10 @@ class Controller(object):
buff = self.view.search(buffer.name, buffer.account)
answer = buffer.remove_buffer()
if answer == False: return
if hasattr(buff, "timer"):
log.debug("destroying buffer...")
if hasattr(buffer, "timer"):
log.debug("Stopping timer...")
buff.timer.cancel()
buffer.timer.cancel()
log.debug("Timer cancelled.")
self.right()
self.view.delete_buffer(buff)

View File

@@ -40,9 +40,8 @@ class basicTweet(object):
dlg = translator.gui.translateDialog()
if dlg.get_response() == widgetUtils.OK:
text_to_translate = self.message.get_text()
source = [x[0] for x in translator.translator.available_languages()][dlg.get("source_lang")]
dest = [x[0] for x in translator.translator.available_languages()][dlg.get("dest_lang")]
msg = translator.translator.translate(text=text_to_translate, source=source, target=dest)
msg = translator.translator.translate(text=text_to_translate, target=dest)
self.message.set_text(msg)
self.text_processor()
self.message.text_focus()

View File

@@ -1,11 +1,13 @@
# -*- coding: utf-8 -*-
from yandex_translate import YandexTranslate
def translate(text="", source="auto", target="en"):
def translate(text="", target="en"):
t = YandexTranslate("trnsl.1.1.20161012T134532Z.d01b9c75fc39aa74.7d1be75a5166a80583eeb020e10f584168da6bf7")
return t.translate(text, target)["text"][0]
vars = dict(text=text, lang=target)
return t.translate(**vars)["text"][0]
supported_langs = None
d = None
languages = {
"af": _(u"Afrikaans"),
"sq": _(u"Albanian"),
@@ -71,7 +73,7 @@ languages = {
"ps": _(u"Pashto"),
"fa": _(u"Persian"),
"pl": _(u"Polish"),
"pt-PT": _(u"Portuguese"),
"pt": _(u"Portuguese"),
"pa": _(u"Punjabi"),
"ro": _(u"Romanian"),
"ru": _(u"Russian"),
@@ -101,8 +103,11 @@ languages = {
}
def available_languages():
l = languages.keys()
d = languages.values()
l.insert(0, '')
d.insert(0, _(u"autodetect"))
return sorted(zip(l, d))
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))

View File

@@ -25,15 +25,11 @@ class translateDialog(baseDialog.BaseWXDialog):
super(translateDialog, self).__init__(None, -1, title=_(u"Translate message"))
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
staticSource = wx.StaticText(panel, -1, _(u"Source language"))
self.source_lang = wx.ComboBox(panel, -1, choices=[x[1] for x in translator.available_languages()], style = wx.CB_READONLY)
self.source_lang.SetFocus()
staticDest = wx.StaticText(panel, -1, _(u"Target language"))
self.source_lang.SetSelection(0)
self.dest_lang = wx.ComboBox(panel, -1, choices=[x[1] for x in translator.available_languages()], style = wx.CB_READONLY)
self.dest_lang.SetFocus()
self.dest_lang.SetSelection(0)
listSizer = wx.BoxSizer(wx.HORIZONTAL)
listSizer.Add(staticSource)
listSizer.Add(self.source_lang)
listSizer.Add(staticDest)
listSizer.Add(self.dest_lang)
ok = wx.Button(panel, wx.ID_OK)

View File

@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
""" The main session object. Here are the twitter functions to interact with the "model" of TWBlue."""
import wx
import urllib2
import config
import twitter
@@ -16,10 +17,11 @@ import config_utils
import shelve
import application
import os
from mysc.thread_utils import stream_threaded
from mysc.thread_utils import stream_threaded, call_threaded
from pubsub import pub
log = logging.getLogger("sessionmanager.session")
from long_tweets import tweets, twishort
from wxUI import authorisationDialog
sessions = {}
@@ -166,7 +168,20 @@ class Session(object):
if self.logged == True:
raise Exceptions.AlreadyAuthorisedError("The authorisation process is not needed at this time.")
else:
self.twitter.authorise(self.settings)
self.authorisation_thread = call_threaded(self.twitter.authorise, self.settings)
self.authorisation_dialog = authorisationDialog()
self.authorisation_dialog.cancel.Bind(wx.EVT_BUTTON, self.authorisation_cancelled)
pub.subscribe(self.authorisation_accepted, "authorisation-accepted")
self.authorisation_dialog.ShowModal()
def authorisation_cancelled(self, *args, **kwargs):
pub.sendMessage("authorisation-cancelled")
self.authorisation_dialog.Destroy()
del self.authorisation_dialog
def authorisation_accepted(self):
pub.unsubscribe(self.authorisation_accepted, "authorisation-accepted")
self.authorisation_dialog.Destroy()
def get_more_items(self, update_function, users=False, name=None, *args, **kwargs):
results = []

View File

@@ -73,4 +73,17 @@ class sessionManagerWindow(wx.Dialog):
self.configuration.Hide()
def destroy(self):
self.Destroy()
self.Destroy()
class authorisationDialog(wx.Dialog):
def __init__(self):
super(authorisationDialog, self).__init__(parent=None, title=_(u"Authorising account..."))
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
self.text = wx.TextCtrl(panel, -1, _("Waiting for account authorisation..."), style=wx.TE_READONLY|wx.TE_MULTILINE)
self.cancel = wx.Button(panel, wx.ID_CANCEL)
sizer.Add(self.text, 0, wx.ALL, 5)
sizer.Add(self.cancel, 0, wx.ALL, 5)
panel.SetSizer(sizer)
min = sizer.CalcMin()
self.SetClientSize(min)

View File

@@ -104,7 +104,7 @@ class soundSystem(object):
sound_object.play()
class URLStream(object):
def __init__(self,url=None):
def __init__(self, url=None):
self.url = url
self.prepared = False
log.debug("URL Player initialized")
@@ -118,12 +118,10 @@ class URLStream(object):
transformer = audio_services.find_url_transformer(self.url)
self.url = transformer(self.url)
log.debug("Transformed URL: %s. Prepared" % (self.url,))
self.prepared = True
else:
self.url = url
log.debug("Transformed URL: %s. Prepared" % (self.url,))
self.prepared = True
self.prepared = True
def seek(self,step):
pos=self.stream.get_position()
@@ -154,7 +152,7 @@ class URLStream(object):
self.stream.volume = float(volume)
self.stream.play()
log.debug("played")
# call_threaded(self.delete_when_done)
self.prepared=False
def stop_audio(self,delete=False):
if hasattr(self, "stream"):
@@ -167,6 +165,7 @@ class URLStream(object):
if delete:
del self.stream
log.debug("Deleted audio stream.")
self.prepared=False
return True
else:
return False

View File

@@ -2,11 +2,12 @@
import BaseHTTPServer
import application
from urlparse import urlparse, parse_qs
from pubsub import pub
logged = False
verifier = None
class handler(BaseHTTPServer.BaseHTTPRequestHandler):
class handler(BaseHTTPServer.BaseHTTPRequestHandler, object):
def do_GET(self):
global logged
@@ -18,4 +19,14 @@ class handler(BaseHTTPServer.BaseHTTPRequestHandler):
global verifier
verifier = params.get('oauth_verifier', [None])[0]
self.wfile.write(u"You have successfully logged into Twitter with {0}. You can close this window now.".format(application.name))
pub.sendMessage("authorisation-accepted")
pub.unsubscribe(self.cancelled, "authorisation-cancelled")
self.finish()
def __init__(self, *args, **kwargs):
pub.subscribe(self.cancelled, "authorisation-cancelled")
super(handler, self).__init__(*args, **kwargs)
def cancelled(self):
pub.unsubscribe(self.cancelled, "authorisation-cancelled")
self.finish()

View File

@@ -184,7 +184,7 @@ def compose_event(data, username, show_screen_names=False):
else: event = _(u"%s(@%s) has removed you from the list %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["name"])
elif data["event"] == "list_user_subscribed":
if data["source"]["screen_name"] == username: event = _(u"You've subscribed to the list %s, which is owned by %s(@%s)") % (data["target_object"]["name"], data["target"]["name"], data["target"]["screen_name"])
else: event = _(u"%s(@%s) has suscribed you to the list %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["name"])
else: event = _(u"%s(@%s) has subscribed you to the list %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["name"])
elif data["event"] == "list_user_unsubscribed":
if data["source"]["screen_name"] == username: event = _(u"You've unsubscribed from the list %s, which is owned by %s(@%s)") % (data["target_object"]["name"], data["target"]["name"], data["target"]["screen_name"])
else: event = _("You've been unsubscribed from the list %s, which is owned by %s(@%s)") % (data["target_object"]["name"], data["source"]["name"], data["source"]["screen_name"])

View File

@@ -29,7 +29,12 @@ def find_urls (tweet):
i = "full_text"
else:
i = "text"
return [s[0] for s in url_re.findall(tweet[i])]
shorten_urls = find_urls_in_text(tweet[i])
for url in range(0, len(shorten_urls)):
try:
urls.append(tweet["entities"]["urls"][url]["expanded_url"])
except: pass
return urls
def find_item(id, listItem):
for i in range(0, len(listItem)):

View File

@@ -19,7 +19,7 @@ Questions, comments? ryan@venodesigns.net
"""
__author__ = 'Ryan McGrath <ryan@venodesigns.net>'
__version__ = '3.3.0'
__version__ = '3.6.0'
from .api import Twython
from .streaming import TwythonStreamer

View File

@@ -145,6 +145,7 @@ class Twython(EndpointsMixin, object):
else:
params = params
files = list()
requests_args = {}
for k, v in self.client_args.items():
# Maybe this should be set as a class variable and only done once?
@@ -195,17 +196,16 @@ class Twython(EndpointsMixin, object):
error_message,
error_code=response.status_code,
retry_after=response.headers.get('X-Rate-Limit-Reset'))
content=""
try:
if response.status_code == 204:
content = response.content
else:
content = response.json()
except ValueError:
# Send the response as is for working with /media/metadata/create.json.
content = response.content
# raise TwythonError('Response was not valid JSON. \
# Unable to decode.')
if response.content!="":
raise TwythonError('Response was not valid JSON. \
Unable to decode.')
return content
@@ -258,8 +258,10 @@ class Twython(EndpointsMixin, object):
url = endpoint
else:
url = '%s/%s.json' % (self.api_url % version, endpoint)
content = self._request(url, method=method, params=params,
api_call=url)
return content
def get(self, endpoint, params=None, version='1.1'):
@@ -473,6 +475,11 @@ class Twython(EndpointsMixin, object):
>>> print result
"""
if not callable(function):
raise TypeError('.cursor() takes a Twython function as its first \
argument. Did you provide the result of a \
function call?')
if not hasattr(function, 'iter_mode'):
raise TwythonError('Unable to create generator for Twython \
method "%s"' % function.__name__)
@@ -531,7 +538,7 @@ class Twython(EndpointsMixin, object):
@staticmethod
def html_for_tweet(tweet, use_display_url=True, use_expanded_url=False, expand_quoted_status=False):
"""Return HTML for a tweet (urls, mentions, hashtags replaced with links)
"""Return HTML for a tweet (urls, mentions, hashtags, symbols replaced with links)
:param tweet: Tweet object from received from Twitter API
:param use_display_url: Use display URL to represent link
@@ -547,62 +554,116 @@ class Twython(EndpointsMixin, object):
if 'retweeted_status' in tweet:
tweet = tweet['retweeted_status']
if 'extended_tweet' in tweet:
tweet = tweet['extended_tweet']
orig_tweet_text = tweet.get('full_text') or tweet['text']
display_text_range = tweet.get('display_text_range') or [0, len(orig_tweet_text)]
display_text_start, display_text_end = display_text_range[0], display_text_range[1]
display_text = orig_tweet_text[display_text_start:display_text_end]
prefix_text = orig_tweet_text[0:display_text_start]
suffix_text = orig_tweet_text[display_text_end:len(orig_tweet_text)]
if 'entities' in tweet:
text = tweet['text']
entities = tweet['entities']
# We'll put all the bits of replacement HTML and their starts/ends
# in this list:
entities = []
# Mentions
for entity in sorted(entities['user_mentions'],
key=lambda mention: len(mention['screen_name']), reverse=True):
start, end = entity['indices'][0], entity['indices'][1]
if 'user_mentions' in tweet['entities']:
for entity in tweet['entities']['user_mentions']:
temp = {}
temp['start'] = entity['indices'][0]
temp['end'] = entity['indices'][1]
mention_html = '<a href="https://twitter.com/%(screen_name)s" class="twython-mention">@%(screen_name)s</a>'
text = re.sub(r'(?<!>)' + tweet['text'][start:end] + '(?!</a>)',
mention_html % {'screen_name': entity['screen_name']}, text)
mention_html = '<a href="https://twitter.com/%(screen_name)s" class="twython-mention">@%(screen_name)s</a>' % {'screen_name': entity['screen_name']}
if display_text_start <= temp['start'] <= display_text_end:
temp['replacement'] = mention_html
entities.append(temp)
else:
# Make the '@username' at the start, before
# display_text, into a link:
sub_expr = r'(?<!>)' + orig_tweet_text[temp['start']:temp['end']] + '(?!</a>)'
prefix_text = re.sub(sub_expr, mention_html, prefix_text)
# Hashtags
for entity in sorted(entities['hashtags'],
key=lambda hashtag: len(hashtag['text']), reverse=True):
start, end = entity['indices'][0], entity['indices'][1]
if 'hashtags' in tweet['entities']:
for entity in tweet['entities']['hashtags']:
temp = {}
temp['start'] = entity['indices'][0]
temp['end'] = entity['indices'][1]
hashtag_html = '<a href="https://twitter.com/search?q=%%23%(hashtag)s" class="twython-hashtag">#%(hashtag)s</a>'
text = re.sub(r'(?<!>)' + tweet['text'][start:end] + '(?!</a>)',
hashtag_html % {'hashtag': entity['text']}, text)
url_html = '<a href="https://twitter.com/search?q=%%23%(hashtag)s" class="twython-hashtag">#%(hashtag)s</a>' % {'hashtag': entity['text']}
# Urls
for entity in entities['urls']:
start, end = entity['indices'][0], entity['indices'][1]
if use_display_url and entity.get('display_url') \
and not use_expanded_url:
shown_url = entity['display_url']
elif use_expanded_url and entity.get('expanded_url'):
shown_url = entity['expanded_url']
else:
shown_url = entity['url']
temp['replacement'] = url_html
entities.append(temp)
url_html = '<a href="%s" class="twython-url">%s</a>'
text = text.replace(tweet['text'][start:end],
url_html % (entity['url'], shown_url))
# Symbols
if 'symbols' in tweet['entities']:
for entity in tweet['entities']['symbols']:
temp = {}
temp['start'] = entity['indices'][0]
temp['end'] = entity['indices'][1]
# Media
if 'media' in entities:
for entity in entities['media']:
start, end = entity['indices'][0], entity['indices'][1]
if use_display_url and entity.get('display_url') \
and not use_expanded_url:
url_html = '<a href="https://twitter.com/search?q=%%24%(symbol)s" class="twython-symbol">$%(symbol)s</a>' % {'symbol': entity['text']}
temp['replacement'] = url_html
entities.append(temp)
# URLs
if 'urls' in tweet['entities']:
for entity in tweet['entities']['urls']:
temp = {}
temp['start'] = entity['indices'][0]
temp['end'] = entity['indices'][1]
if use_display_url and entity.get('display_url') and not use_expanded_url:
shown_url = entity['display_url']
elif use_expanded_url and entity.get('expanded_url'):
shown_url = entity['expanded_url']
else:
shown_url = entity['url']
url_html = '<a href="%s" class="twython-media">%s</a>'
text = text.replace(tweet['text'][start:end],
url_html % (entity['url'], shown_url))
url_html = '<a href="%s" class="twython-url">%s</a>' % (entity['url'], shown_url)
if expand_quoted_status and tweet.get('is_quote_status'):
if display_text_start <= temp['start'] <= display_text_end:
temp['replacement'] = url_html
entities.append(temp)
else:
suffix_text = suffix_text.replace(orig_tweet_text[temp['start']:temp['end']], url_html)
if 'media' in tweet['entities']:
for entity in tweet['entities']['media']:
temp = {}
temp['start'] = entity['indices'][0]
temp['end'] = entity['indices'][1]
if use_display_url and entity.get('display_url') and not use_expanded_url:
shown_url = entity['display_url']
elif use_expanded_url and entity.get('expanded_url'):
shown_url = entity['expanded_url']
else:
shown_url = entity['url']
url_html = '<a href="%s" class="twython-media">%s</a>' % (entity['url'], shown_url)
if display_text_start <= temp['start'] <= display_text_end:
temp['replacement'] = url_html
entities.append(temp)
else:
suffix_text = suffix_text.replace(orig_tweet_text[temp['start']:temp['end']], url_html)
# Now do all the replacements, starting from the end, so that the
# start/end indices still work:
for entity in sorted(entities, key=lambda e: e['start'], reverse=True):
display_text = display_text[0:entity['start']] + entity['replacement'] + display_text[entity['end']:]
quote_text = ''
if expand_quoted_status and tweet.get('is_quote_status') and tweet.get('quoted_status'):
quoted_status = tweet['quoted_status']
text += '<blockquote class="twython-quote">%(quote)s<cite><a href="%(quote_tweet_link)s">' \
quote_text += '<blockquote class="twython-quote">%(quote)s<cite><a href="%(quote_tweet_link)s">' \
'<span class="twython-quote-user-name">%(quote_user_name)s</span>' \
'<span class="twython-quote-user-screenname">@%(quote_user_screen_name)s</span></a>' \
'</cite></blockquote>' % \
@@ -612,4 +673,9 @@ class Twython(EndpointsMixin, object):
'quote_user_name': quoted_status['user']['name'],
'quote_user_screen_name': quoted_status['user']['screen_name']}
return text
return '%(prefix)s%(display)s%(suffix)s%(quote)s' % {
'prefix': '<span class="twython-tweet-prefix">%s</span>' % prefix_text if prefix_text else '',
'display': display_text,
'suffix': '<span class="twython-tweet-suffix">%s</span>' % suffix_text if suffix_text else '',
'quote': quote_text
}

View File

@@ -17,10 +17,12 @@ https://dev.twitter.com/docs/api/1.1
import json
import os
import warnings
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
from io import BytesIO
from time import sleep
#try:
#from StringIO import StringIO
#except ImportError:
#from io import StringIO
from .advisory import TwythonDeprecationWarning
@@ -143,15 +145,20 @@ class EndpointsMixin(object):
Docs:
https://dev.twitter.com/rest/reference/post/media/upload
"""
# https://dev.twitter.com/rest/reference/get/media/upload-status
if params and params.get('command', '') == 'STATUS':
return self.get('https://upload.twitter.com/1.1/media/upload.json', params=params)
return self.post('https://upload.twitter.com/1.1/media/upload.json', params=params)
def set_description(self, **params):
""" Adds a description to an image."""
# This method only accepts strings, no dictionaries.
def create_metadata(self, **params):
""" Adds metadata to a media element, such as image descriptions for visually impaired.
Docs: https://developer.twitter.com/en/docs/media/upload-media/api-reference/post-media-metadata-create
"""
params = json.dumps(params)
return self.post("media/metadata/create", params=params)
return self.post("https://upload.twitter.com/1.1/media/metadata/create.json", params=params)
def upload_video(self, media, media_type, size=None):
def upload_video(self, media, media_type, media_category=None, size=None, check_progress=False):
"""Uploads video file to Twitter servers in chunks. The file will be available to be attached
to a status for 60 minutes. To attach to a update, pass a list of returned media ids
to the 'update_status' method using the 'media_ids' param.
@@ -176,7 +183,8 @@ class EndpointsMixin(object):
params = {
'command': 'INIT',
'media_type': media_type,
'total_bytes': size
'total_bytes': size,
'media_category': media_category
}
response_init = self.post(upload_url, params=params)
media_id = response_init['media_id']
@@ -187,7 +195,7 @@ class EndpointsMixin(object):
data = media.read(1*1024*1024)
if not data:
break
media_chunk = StringIO()
media_chunk = BytesIO()
media_chunk.write(data)
media_chunk.seek(0)
@@ -205,7 +213,38 @@ class EndpointsMixin(object):
'command': 'FINALIZE',
'media_id': media_id
}
return self.post(upload_url, params=params)
response = self.post(upload_url, params=params)
# Only get the status if explicity asked to
# Default to False
if check_progress:
# Stage 4: STATUS call if still processing
params = {
'command': 'STATUS',
'media_id': media_id
}
# added code to handle if media_category is NOT set and check_progress=True
# the API will return a NoneType object in this case
try:
processing_state = response.get('processing_info').get('state')
except AttributeError:
return response
if processing_state:
while (processing_state == 'pending' or processing_state == 'in_progress') :
# get the secs to wait
check_after_secs = response.get('processing_info').get('check_after_secs')
if check_after_secs:
sleep(check_after_secs)
response = self.get(upload_url, params=params)
# get new state after waiting
processing_state = response.get('processing_info').get('state')
return response
def get_oembed_tweet(self, **params):
"""Returns information allowing the creation of an embedded

View File

@@ -10,11 +10,12 @@ logger = logging.getLogger("updater")
def do_update(endpoint=application.update_url):
try:
update.perform_update(endpoint=endpoint, current_version=application.version, app_name=application.name, update_available_callback=available_update_dialog, progress_callback=progress_callback, update_complete_callback=update_finished)
result = update.perform_update(endpoint=endpoint, current_version=application.version, app_name=application.name, update_available_callback=available_update_dialog, progress_callback=progress_callback, update_complete_callback=update_finished)
except:
if endpoint == application.update_url:
logger.error("Update failed! Using mirror URL...")
return do_update(endpoint=application.mirror_update_url)
else:
logger.exception("Update failed.")
output.speak("An exception occurred while attempting to update " + application.name + ". If this message persists, contact the " + application.name + " developers. More information about the exception has been written to the error log.",True)
output.speak("An exception occurred while attempting to update " + application.name + ". If this message persists, contact the " + application.name + " developers. More information about the exception has been written to the error log.",True)
return result

View File

@@ -25,7 +25,7 @@ def unshorten (url, service=None, **kwargs):
def default_service ():
return shorteners.TinyurlShortener
return shorteners.AcortameShortener
def find_service (service, **kwargs):
for i in shorteners.__all__:

View File

@@ -6,4 +6,5 @@ from tinyarrows import TinyArrowsShortener
from tinyurl import TinyurlShortener
from xedcc import XedccShortener
from clckru import ClckruShortener
__all__ = ["HKCShortener", "IsgdShortener", "OnjmeShortener", "TinyArrowsShortener", "TinyurlShortener", "XedccShortener", "ClckruShortener"]
from acortame import AcortameShortener
__all__ = ["HKCShortener", "IsgdShortener", "OnjmeShortener", "TinyArrowsShortener", "TinyurlShortener", "XedccShortener", "ClckruShortener", "AcortameShortener"]

View File

@@ -0,0 +1,27 @@
from url_shortener import URLShortener
import requests
import urllib
class AcortameShortener (URLShortener):
def __init__(self, *args, **kwargs):
self.name = "acorta.me"
super(AcortameShortener, self).__init__(*args, **kwargs)
def _shorten (self, url):
answer = url
api = requests.get ("https://acorta.me/api.php?action=shorturl&format=simple&url=" + urllib.quote(url))
if api.status_code == 200:
answer = api.text
return answer
def created_url (self, url):
return 'acorta.me' in url
def unshorten (self, url):
if not 'acorta.me' in url:
#use generic expand method
return super(AcortameShortener, self).unshorten(url)
answer = url
api = requests.get ("https://acorta.me/api.php?action=expand&format=simple&shorturl=" + urllib.quote(url))
if api.status_code == 200:
answer = api.text
return answer

View File

@@ -1,19 +1,18 @@
import urllib
import requests
from url_shortener import URLShortener
class ClckruShortener (URLShortener):
def __init__ (self, *args, **kwargs):
self.name = "clck.ru"
return super(ClckruShortener, self).__init__(*args, **kwargs)
super(ClckruShortener, self).__init__(*args, **kwargs)
def _shorten (self, url):
answer = url
api = urllib.urlopen ("http://clck.ru/--?url=" + urllib.quote(url))
if api.getcode() == 200:
answer = api.read()
api.close()
api = requests.get ("http://clck.ru/--?url=" + urllib.quote(url))
if api.status_code == 200:
answer = api.text
return answer
def created_url (self, url):

View File

@@ -1,5 +1,5 @@
import urllib
import requests
from url_shortener import URLShortener
class HKCShortener (URLShortener):
@@ -9,10 +9,9 @@ class HKCShortener (URLShortener):
def _shorten (self, url):
answer = url
api = urllib.urlopen ("http://hkc.im/yourls-api.php?action=shorturl&format=simple&url=" + urllib.quote(url))
if api.getcode() == 200:
answer = api.read()
api.close()
api = requests.get ("http://hkc.im/yourls-api.php?action=shorturl&format=simple&url=" + urllib.quote(url))
if api.status_code == 200:
answer = api.text
return answer
def created_url (self, url):

View File

@@ -1,19 +1,18 @@
import urllib
import requests
from url_shortener import URLShortener
class IsgdShortener (URLShortener):
def __init__ (self, *args, **kwargs):
self.name = "Is.gd"
return super(IsgdShortener, self).__init__(*args, **kwargs)
super(IsgdShortener, self).__init__(*args, **kwargs)
def _shorten (self, url):
answer = url
api = urllib.urlopen ("http://is.gd/api.php?longurl=" + urllib.quote(url))
if api.getcode() == 200:
answer = api.read()
api.close()
api = requests.get ("http://is.gd/api.php?longurl=" + urllib.quote(url))
if api.status_code == 200:
answer = api.text
return answer
def created_url (self, url):

View File

@@ -1,5 +1,5 @@
import urllib
import requests
from url_shortener import URLShortener
class OnjmeShortener (URLShortener):
@@ -9,10 +9,9 @@ class OnjmeShortener (URLShortener):
def _shorten (self, url):
answer = url
api = urllib.urlopen ("http://onj.me/yourls-api.php?action=shorturl&format=simple&url=" + urllib.quote(url))
if api.getcode() == 200:
answer = api.read()
api.close()
api = requests.get ("http://onj.me/yourls-api.php?action=shorturl&format=simple&url=" + urllib.quote(url))
if api.status_code == 200:
answer = api.text
return answer
def created_url (self, url):

View File

@@ -1,5 +1,5 @@
import urllib
import requests
from url_shortener import URLShortener
class TinyArrowsShortener (URLShortener):
@@ -9,8 +9,10 @@ class TinyArrowsShortener (URLShortener):
def _shorten (self, url):
answer = url
answer = urllib.urlopen("http://tinyarro.ws/api-create.php?utfpure=1&url=%s" % urllib.quote(url)).read()
api = requests.get("http://tinyarro.ws/api-create.php?utfpure=1&url=%s" % urllib.quote(url))
if api.status_code == 200:
answer = api.text
return answer.decode('UTF-8')
def created_url(self, url):
return False
return "tinyarro.ws" in url

View File

@@ -1,4 +1,5 @@
from url_shortener import URLShortener
import requests
import urllib
class TinyurlShortener (URLShortener):
def __init__(self, *args, **kwargs):
@@ -6,12 +7,10 @@ class TinyurlShortener (URLShortener):
super(TinyurlShortener, self).__init__(*args, **kwargs)
def _shorten (self, url):
answer = url
api = urllib.urlopen ("http://tinyurl.com/api-create.php?url=" + urllib.quote(url))
if api.getcode() == 200:
answer = api.read()
api.close()
api = requests.get ("http://tinyurl.com/api-create.php?url=" + urllib.quote(url))
if api.status_code == 200:
answer = api.text
return answer
def created_url (self, url):

View File

@@ -1,6 +1,4 @@
from httplib import HTTPConnection
from urlparse import urlparse
import requests
class URLShortener (object):
@@ -22,12 +20,18 @@ class URLShortener (object):
raise NotImplementedError
def unshorten(self, url):
working = urlparse(url)
if not working.netloc:
raise TypeError, "Unable to parse URL."
con = HTTPConnection(working.netloc)
con.connect()
con.request('GET', working.path)
resp = con.getresponse()
con.close()
return resp.getheader('location')
try:
r=requests.head(url)
if 'location' in r.headers.keys():
if 'dropbox.com' in r.headers['location']:
return handle_dropbox(r.headers['location'])
else:
return r.headers['location']
except:
return url #we cannot expand
def handle_dropbox(url):
if url.endswith("dl=1"):
return url
else:
return url.replace("dl=0", "dl=1")

View File

@@ -1,5 +1,5 @@
import urllib
import requests
from url_shortener import URLShortener
class XedccShortener (URLShortener):
@@ -9,10 +9,9 @@ class XedccShortener (URLShortener):
def _shorten (self, url):
answer = url
api = urllib.urlopen ("http://xed.cc/yourls-api.php?action=shorturl&format=simple&url=" + urllib.quote(url))
if api.getcode() == 200:
answer = api.read()
api.close()
api = requests.get ("http://xed.cc/yourls-api.php?action=shorturl&format=simple&url=" + urllib.quote(url))
if api.status_code == 200:
answer = api.text
return answer
def created_url (self, url):

View File

@@ -26,8 +26,7 @@ class searchDialog(baseDialog.BaseWXDialog):
radioSizer.Add(self.users, 0, wx.ALL, 5)
sizer.Add(radioSizer, 0, wx.ALL, 5)
lang = wx.StaticText(panel, -1, _(u"&Language for results: "))
langs = [x[1] for x in translator.translator.available_languages()]
langs[:] = langs[1:]
langs = [x for x in translator.translator.languages.values()]
langs.insert(0, _(u"any"))
self.lang = wx.ComboBox(panel, -1, choices=langs, value=langs[0], style = wx.CB_READONLY)
langBox = wx.BoxSizer(wx.HORIZONTAL)
@@ -51,7 +50,12 @@ class searchDialog(baseDialog.BaseWXDialog):
self.SetClientSize(sizer.CalcMin())
def get_language(self):
return [x[0] for x in translator.translator.available_languages()][self.lang.GetSelection()]
l = self.lang.GetStringSelection()
if l == _(u"any"):
return ""
for langcode, langname in translator.translator.languages.iteritems():
if langname == l:
return langcode
def get_result_type(self):
r = self.resultstype.GetValue()