2014-10-27 16:29:04 -06:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import url_shortener, re
|
|
|
|
import output
|
|
|
|
from twython import TwythonError
|
|
|
|
import config
|
2015-02-03 09:59:18 -06:00
|
|
|
import logging
|
2015-05-12 13:31:51 -04:00
|
|
|
import requests
|
2015-05-13 12:49:22 -04:00
|
|
|
import time
|
|
|
|
import sound
|
2015-02-03 09:59:18 -06:00
|
|
|
log = logging.getLogger("twitter.utils")
|
|
|
|
""" Some utilities for the twitter interface."""
|
2014-10-27 16:29:04 -06:00
|
|
|
|
|
|
|
__version__ = 0.1
|
|
|
|
__doc__ = "Find urls in tweets and #audio hashtag."
|
|
|
|
|
|
|
|
url_re = re.compile(r"(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'\".,<>?«»“”‘’]))")
|
|
|
|
|
|
|
|
url_re2 = re.compile("(?:\w+://|www\.)[^ ,.?!#%=+][^ ]*")
|
|
|
|
bad_chars = '\'\\.,[](){}:;"'
|
|
|
|
|
|
|
|
def find_urls_in_text(text):
|
|
|
|
return [s.strip(bad_chars) for s in url_re2.findall(text)]
|
|
|
|
|
|
|
|
def find_urls (tweet):
|
|
|
|
urls = []
|
2017-11-29 10:55:42 -06:00
|
|
|
# Let's add URLS from tweet entities.
|
2018-07-20 10:04:53 -05:00
|
|
|
if tweet.has_key("message_create"):
|
|
|
|
entities = tweet["message_create"]["message_data"]["entities"]
|
|
|
|
else:
|
|
|
|
entities = tweet["entities"]
|
|
|
|
for i in entities["urls"]:
|
2017-11-29 10:55:42 -06:00
|
|
|
if i["expanded_url"] not in urls:
|
|
|
|
urls.append(i["expanded_url"])
|
|
|
|
if tweet.has_key("quoted_status"):
|
|
|
|
for i in tweet["quoted_status"]["entities"]["urls"]:
|
|
|
|
if i["expanded_url"] not in urls:
|
|
|
|
urls.append(i["expanded_url"])
|
|
|
|
if tweet.has_key("retweeted_status"):
|
|
|
|
for i in tweet["retweeted_status"]["entities"]["urls"]:
|
|
|
|
if i["expanded_url"] not in urls:
|
|
|
|
urls.append(i["expanded_url"])
|
|
|
|
if tweet["retweeted_status"].has_key("quoted_status"):
|
|
|
|
for i in tweet["retweeted_status"]["quoted_status"]["entities"]["urls"]:
|
|
|
|
if i["expanded_url"] not in urls:
|
|
|
|
urls.append(i["expanded_url"])
|
2016-04-28 13:54:06 -05:00
|
|
|
if tweet.has_key("message"):
|
|
|
|
i = "message"
|
2016-09-28 17:25:03 -05:00
|
|
|
elif tweet.has_key("full_text"):
|
|
|
|
i = "full_text"
|
2016-04-28 13:54:06 -05:00
|
|
|
else:
|
|
|
|
i = "text"
|
2018-07-20 10:04:53 -05:00
|
|
|
if tweet.has_key("message_create"):
|
|
|
|
extracted_urls = find_urls_in_text(tweet["message_create"]["message_data"]["text"])
|
|
|
|
else:
|
|
|
|
extracted_urls = find_urls_in_text(tweet[i])
|
2017-11-29 10:55:42 -06:00
|
|
|
# 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:
|
|
|
|
urls.append(i)
|
2017-09-17 23:19:04 -05:00
|
|
|
return urls
|
2014-10-27 16:29:04 -06:00
|
|
|
|
|
|
|
def find_item(id, listItem):
|
|
|
|
for i in range(0, len(listItem)):
|
|
|
|
if listItem[i]["id"] == id: return i
|
|
|
|
return None
|
|
|
|
|
|
|
|
def find_list(name, lists):
|
|
|
|
for i in range(0, len(lists)):
|
2015-08-10 09:26:07 -05:00
|
|
|
if lists[i]["name"] == name: return lists[i]["id"]
|
2014-10-27 16:29:04 -06:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2015-06-08 05:41:48 -05:00
|
|
|
def is_audio(tweet):
|
2015-05-12 20:19:39 -04:00
|
|
|
try:
|
2015-05-12 22:12:14 -04:00
|
|
|
if len(find_urls(tweet)) < 1:
|
|
|
|
return False
|
2018-07-20 10:04:53 -05:00
|
|
|
if tweet.has_key("message_create"):
|
|
|
|
entities = tweet["message_create"]["message_data"]["entities"]
|
|
|
|
else:
|
|
|
|
entities = tweet["entities"]
|
|
|
|
if len(entities["hashtags"]) > 0:
|
|
|
|
for i in entities["hashtags"]:
|
2015-05-12 20:19:39 -04:00
|
|
|
if i["text"] == "audio":
|
|
|
|
return True
|
2018-07-20 10:04:53 -05:00
|
|
|
except IndexError:
|
2016-09-28 17:25:03 -05:00
|
|
|
print tweet["entities"]["hashtags"]
|
2015-05-12 20:19:39 -04:00
|
|
|
log.exception("Exception while executing is_audio hashtag algorithm")
|
2014-10-27 16:29:04 -06:00
|
|
|
|
2015-02-03 05:10:01 -06:00
|
|
|
def is_geocoded(tweet):
|
|
|
|
if tweet.has_key("coordinates") and tweet["coordinates"] != None:
|
|
|
|
return True
|
|
|
|
|
2017-01-07 06:58:53 -06:00
|
|
|
def is_media(tweet):
|
2018-07-20 10:04:53 -05:00
|
|
|
if tweet.has_key("message_create"):
|
|
|
|
entities = tweet["message_create"]["message_data"]["entities"]
|
|
|
|
else:
|
|
|
|
entities = tweet["entities"]
|
|
|
|
if entities.has_key("media") == False:
|
2017-01-07 06:58:53 -06:00
|
|
|
return False
|
2018-07-20 10:04:53 -05:00
|
|
|
for i in entities["media"]:
|
2017-01-07 06:58:53 -06:00
|
|
|
if i.has_key("type") and i["type"] == "photo":
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
2016-12-09 10:15:39 -06:00
|
|
|
def get_all_mentioned(tweet, conf, field="screen_name"):
|
2014-10-27 16:29:04 -06:00
|
|
|
""" Gets all users that has been mentioned."""
|
2016-12-09 10:15:39 -06:00
|
|
|
results = []
|
2016-10-04 09:35:18 -05:00
|
|
|
for i in tweet["entities"]["user_mentions"]:
|
2015-01-02 09:38:44 -06:00
|
|
|
if i["screen_name"] != conf["user_name"] and i["screen_name"] != tweet["user"]["screen_name"]:
|
2016-12-09 10:15:39 -06:00
|
|
|
if i[field] not in results:
|
|
|
|
results.append(i[field])
|
|
|
|
return results
|
2014-10-27 16:29:04 -06:00
|
|
|
|
2015-01-02 09:38:44 -06:00
|
|
|
def get_all_users(tweet, conf):
|
2014-10-27 16:29:04 -06:00
|
|
|
string = []
|
|
|
|
if tweet.has_key("retweeted_status"):
|
|
|
|
string.append(tweet["user"]["screen_name"])
|
|
|
|
tweet = tweet["retweeted_status"]
|
|
|
|
if tweet.has_key("sender"):
|
|
|
|
string.append(tweet["sender"]["screen_name"])
|
|
|
|
else:
|
2015-01-02 09:38:44 -06:00
|
|
|
if tweet["user"]["screen_name"] != conf["user_name"]:
|
2014-10-27 16:29:04 -06:00
|
|
|
string.append(tweet["user"]["screen_name"])
|
|
|
|
for i in tweet["entities"]["user_mentions"]:
|
2015-01-02 09:38:44 -06:00
|
|
|
if i["screen_name"] != conf["user_name"] and i["screen_name"] != tweet["user"]["screen_name"]:
|
2014-10-27 16:29:04 -06:00
|
|
|
if i["screen_name"] not in string:
|
|
|
|
string.append(i["screen_name"])
|
|
|
|
if len(string) == 0:
|
|
|
|
string.append(tweet["user"]["screen_name"])
|
|
|
|
return string
|
|
|
|
|
|
|
|
def if_user_exists(twitter, user):
|
|
|
|
try:
|
|
|
|
data = twitter.show_user(screen_name=user)
|
2015-03-24 17:28:01 -06:00
|
|
|
return data
|
2015-02-12 10:29:51 -06:00
|
|
|
except TwythonError as err:
|
|
|
|
if err.error_code == 404:
|
|
|
|
return None
|
|
|
|
else:
|
|
|
|
return user
|
2014-10-27 16:29:04 -06:00
|
|
|
|
|
|
|
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)
|
2015-05-14 10:09:31 -04:00
|
|
|
parent.parent.sound.play("error.ogg")
|
2014-10-27 16:29:04 -06:00
|
|
|
return val
|
|
|
|
|
2017-11-13 17:45:01 -06:00
|
|
|
def is_allowed(tweet, settings, buffer_name):
|
|
|
|
clients = settings["twitter"]["ignored_clients"]
|
2015-02-08 05:48:40 -06:00
|
|
|
if tweet.has_key("sender"): return True
|
2014-10-27 16:29:04 -06:00
|
|
|
allowed = True
|
2018-02-27 16:43:16 -06:00
|
|
|
tweet_data = {}
|
|
|
|
if tweet.has_key("retweeted_status"):
|
|
|
|
tweet_data["retweet"] = True
|
|
|
|
if tweet["in_reply_to_status_id_str"] != None:
|
|
|
|
tweet_data["reply"] = True
|
|
|
|
if tweet.has_key("quoted_status"):
|
|
|
|
tweet_data["quote"] = True
|
2014-10-27 16:29:04 -06:00
|
|
|
if tweet.has_key("retweeted_status"): tweet = tweet["retweeted_status"]
|
|
|
|
source = re.sub(r"(?s)<.*?>", "", tweet["source"])
|
2015-02-03 09:59:18 -06:00
|
|
|
for i in clients:
|
2015-01-18 17:19:39 -06:00
|
|
|
if i.lower() == source.lower():
|
2017-11-13 17:45:01 -06:00
|
|
|
return False
|
2018-02-27 16:43:16 -06:00
|
|
|
return filter_tweet(tweet, tweet_data, settings, buffer_name)
|
2017-11-13 17:45:01 -06:00
|
|
|
|
2018-02-27 16:43:16 -06:00
|
|
|
def filter_tweet(tweet, tweet_data, settings, buffer_name):
|
2017-11-20 02:28:40 -06:00
|
|
|
if tweet.has_key("full_text"):
|
|
|
|
value = "full_text"
|
|
|
|
else:
|
|
|
|
value = "text"
|
2017-11-13 17:45:01 -06:00
|
|
|
for i in settings["filters"]:
|
|
|
|
if settings["filters"][i]["in_buffer"] == buffer_name:
|
|
|
|
regexp = settings["filters"][i]["regexp"]
|
|
|
|
word = settings["filters"][i]["word"]
|
2018-03-12 09:01:28 -06:00
|
|
|
# Added if/else for compatibility reasons.
|
|
|
|
if settings["filters"][i].has_key("allow_rts"):
|
|
|
|
allow_rts = settings["filters"][i]["allow_rts"]
|
|
|
|
else:
|
|
|
|
allow_rts = "True"
|
|
|
|
if settings["filters"][i].has_key("allow_quotes"):
|
|
|
|
allow_quotes = settings["filters"][i]["allow_quotes"]
|
|
|
|
else:
|
|
|
|
allow_quotes = "True"
|
|
|
|
if settings["filters"][i].has_key("allow_replies"):
|
|
|
|
allow_replies = settings["filters"][i]["allow_replies"]
|
|
|
|
else:
|
|
|
|
allow_replies = "True"
|
2018-02-27 16:43:16 -06:00
|
|
|
if allow_rts == "False" and tweet_data.has_key("retweet"):
|
|
|
|
return False
|
|
|
|
if allow_quotes == "False" and tweet_data.has_key("quote"):
|
|
|
|
return False
|
|
|
|
if allow_replies == "False" and tweet_data.has_key("reply"):
|
|
|
|
return False
|
2017-11-13 17:45:01 -06:00
|
|
|
if word != "" and settings["filters"][i]["if_word_exists"]:
|
2017-11-22 22:12:05 -06:00
|
|
|
if word in tweet[value]:
|
2017-11-13 17:45:01 -06:00
|
|
|
return False
|
|
|
|
elif word != "" and settings["filters"][i]["if_word_exists"] == False:
|
2017-11-22 22:12:05 -06:00
|
|
|
if word not in tweet[value]:
|
2017-11-13 17:45:01 -06:00
|
|
|
return False
|
2017-11-14 16:56:45 -06:00
|
|
|
if settings["filters"][i]["in_lang"] == "True":
|
2017-11-13 17:45:01 -06:00
|
|
|
if tweet["lang"] not in settings["filters"][i]["languages"]:
|
|
|
|
return False
|
2017-11-14 16:56:45 -06:00
|
|
|
elif settings["filters"][i]["in_lang"] == "False":
|
2017-11-13 17:45:01 -06:00
|
|
|
if tweet["lang"] in settings["filters"][i]["languages"]:
|
|
|
|
return False
|
|
|
|
return True
|
2015-06-13 07:35:04 -05:00
|
|
|
|
|
|
|
def twitter_error(error):
|
|
|
|
if error.error_code == 403:
|
|
|
|
msg = _(u"Sorry, you are not authorised to see this status.")
|
|
|
|
elif error.error_code == 404:
|
|
|
|
msg = _(u"No status found with that ID")
|
2015-06-15 04:57:22 -05:00
|
|
|
else:
|
|
|
|
msg = _(u"Error code {0}").format(error.error_code,)
|
2015-06-13 07:35:04 -05:00
|
|
|
output.speak(msg)
|