1
|
|
|
from base import BotPlugin |
2
|
|
|
from tweepy import OAuthHandler, API as TWITTER_API |
3
|
|
|
from settings import TWITTER as T |
4
|
|
|
from response import random_response |
5
|
|
|
from urllib2 import urlopen |
6
|
|
|
import re |
7
|
|
|
import json |
8
|
|
|
import requests |
9
|
|
|
import lxml.html |
10
|
|
|
import regex |
11
|
|
|
|
12
|
|
|
TWITTER_OAUTH = OAuthHandler(T['consumer_key'], T['consumer_secret']) |
13
|
|
|
TWITTER_OAUTH.set_access_token(T['access_token_key'], T['access_token_secret']) |
14
|
|
|
TWITTER = TWITTER_API(TWITTER_OAUTH) |
15
|
|
|
|
16
|
|
|
# These will be filtered out in _read_webistes |
17
|
|
|
__all_non_web__ = [regex.TWITTER, regex.YOUTUBE, regex.VIMEO] |
18
|
|
|
|
19
|
|
|
VIDEO_RESPONSES = [ |
20
|
|
|
"That video is titled '%(title)s'. " |
21
|
|
|
+ "You will waste %(seconds)ss of your life watching it. ", |
22
|
|
|
"The title of that %(service)s video is '%(title)s'. " |
23
|
|
|
+ "It has been viewed %(views)s times. ", |
24
|
|
|
"Title: '%(title)s', Views: %(views)s, duration: %(seconds)ss.", |
25
|
|
|
"Title of that %(service)s video is '%(title)s'.", |
26
|
|
|
"%(service)s video is titled '%(title)s' and has %(rating)s.", |
27
|
|
|
"Here is the title of that %(service)s video: '%(title)s'.", |
28
|
|
|
"I found the title of that %(service)s video, here it is: '%(title)s'", |
29
|
|
|
"If you click that link you will watch a video titled '%(title)s'. " |
30
|
|
|
+ "Good luck!", |
31
|
|
|
] |
32
|
|
|
|
33
|
|
|
WEB_RESPONSES = [ |
34
|
|
|
"The title of that page is '%(title)s'", |
35
|
|
|
"That page might be about %(title)s", |
36
|
|
|
"That page has an interesting title: '%(title)s'", |
37
|
|
|
"The title of that page makes me want to read the whole thing '%(title)s'", |
38
|
|
|
"%(title)s", |
39
|
|
|
] |
40
|
|
|
|
41
|
|
|
|
42
|
|
|
class ReadLinks(BotPlugin): |
43
|
|
|
|
44
|
|
|
@staticmethod |
45
|
|
|
def _get_tweet_info(status_id): |
46
|
|
|
status = TWITTER.get_status(status_id) |
47
|
|
|
name = status.user.screen_name |
48
|
|
|
text = status.text.replace('\n', ' ') |
49
|
|
|
return name, text |
50
|
|
|
|
51
|
|
|
def _read_twitter(self, channel, msg): |
52
|
|
|
twt_res = regex.TWITTER.search(msg) |
53
|
|
|
if not twt_res: |
54
|
|
|
return |
55
|
|
|
try: |
56
|
|
|
(name, text) = self._get_tweet_info(twt_res.group('id')) |
57
|
|
|
response = unicode("@" + name + " on Twitter says: " + text) |
58
|
|
|
response = response.encode('utf8') |
59
|
|
|
self.bot.say(response, channel) |
60
|
|
|
except: |
61
|
|
|
self.bot.log_error('Could not get tweet from: "' + msg + '"') |
62
|
|
|
self.bot.say('Sorry, I wasn\'t able to read the last tweet :(', |
63
|
|
|
channel) |
64
|
|
|
|
65
|
|
|
@staticmethod |
66
|
|
|
def _get_vimeo_info(video_id): |
67
|
|
|
api_url = "https://vimeo.com/api/v2/video/" + video_id + ".json" |
68
|
|
|
r = requests.get(api_url) |
69
|
|
|
video = json.loads(r.text)[0] |
70
|
|
|
if "stats_number_of_likes" in video: |
71
|
|
|
likes = ("%d likes." % video["stats_number_of_likes"]) |
72
|
|
|
else: |
73
|
|
|
likes = "an unknown number of likes" |
74
|
|
|
return { |
75
|
|
|
'service': "vimeo", |
76
|
|
|
'title': video["title"].encode('utf8'), |
77
|
|
|
'seconds': str(video["duration"]), |
78
|
|
|
'views': str(video["stats_number_of_plays"]), |
79
|
|
|
'rating': likes |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
def _read_vimeo(self, channel, msg): |
83
|
|
|
vimeo_res = regex.VIMEO.search(msg) |
84
|
|
|
if not vimeo_res: |
85
|
|
|
return |
86
|
|
|
try: |
87
|
|
|
video_info = self._get_vimeo_info(vimeo_res.group('id')) |
88
|
|
|
self.bot.say(random_response(VIDEO_RESPONSES) % video_info, |
89
|
|
|
channel) |
90
|
|
|
except: |
91
|
|
|
self.bot.log_error('Could not get title of vimeo link from: "' |
92
|
|
|
+ msg + '"') |
93
|
|
|
self.bot.say('For some reason I couldn\'t read the title of that ' |
94
|
|
|
+ 'vimeo link.', channel) |
95
|
|
|
|
96
|
|
|
@staticmethod |
97
|
|
|
def _get_youtube_info(video_id): |
98
|
|
|
import pafy |
99
|
|
|
url = "https://www.youtube.com/watch?v={0}".format(video_id) |
100
|
|
|
video = pafy.new(url) |
101
|
|
|
|
102
|
|
|
if video.rating is not None: |
103
|
|
|
average_rating = float(video.rating) |
104
|
|
|
rating = ("an average rating of %.2f" % average_rating) |
105
|
|
|
else: |
106
|
|
|
rating = "no rating" |
107
|
|
|
return { |
108
|
|
|
'service': "youtube", |
109
|
|
|
'title': video.title.encode('utf-8'), |
110
|
|
|
'seconds': video.length, |
111
|
|
|
'views': video.viewcount, |
112
|
|
|
'rating': rating |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
def _read_youtube(self, channel, msg): |
116
|
|
|
yt_res = regex.YOUTUBE.search(msg) |
117
|
|
|
if not yt_res: |
118
|
|
|
return |
119
|
|
|
try: |
120
|
|
|
video_info = self._get_youtube_info(yt_res.group('id')) |
121
|
|
|
self.bot.say(random_response(VIDEO_RESPONSES) % video_info, |
122
|
|
|
channel) |
123
|
|
|
except: |
124
|
|
|
self.bot.log_error('Could not get title of youtube link from: "' |
125
|
|
|
+ msg + '"') |
126
|
|
|
self.bot.say('For some reason I couldn\'t read the title of that ' |
127
|
|
|
+ 'youtube link.', channel) |
128
|
|
|
|
129
|
|
|
def _read_websites(self, channel, msg): |
130
|
|
|
links = regex.WEB_URL.findall(msg) |
131
|
|
|
for link in links: |
132
|
|
|
if [r for r in __all_non_web__ if r.search(link)]: |
133
|
|
|
continue |
134
|
|
|
try: |
135
|
|
|
t = lxml.html.parse(urlopen(link)) # nopep8 # nosec: regex.WEB_URL only allows http(s) |
136
|
|
|
t = t.find(".//title").text |
137
|
|
|
t = t.strip().replace('\n', ' ') |
138
|
|
|
if len(re.sub("[^a-zA-Z0-9]", "", t)) >= 5: |
139
|
|
|
self.bot.say(random_response(WEB_RESPONSES) % {'title': t}, |
140
|
|
|
channel) |
141
|
|
|
except: |
142
|
|
|
self.bot.log_error('Could not get title of webpage: "' |
143
|
|
|
+ msg + '"') |
144
|
|
|
|
145
|
|
|
def handle_message(self, channel, nick, msg, line=None): |
146
|
|
|
if "PRIVMSG" in line: |
147
|
|
|
self._read_twitter(channel, msg) |
148
|
|
|
self._read_youtube(channel, msg) |
149
|
|
|
self._read_vimeo(channel, msg) |
150
|
|
|
self._read_websites(channel, msg) |
151
|
|
|
|