mirror of
https://github.com/oddluck/limnoria-plugins.git
synced 2025-04-30 15:31:13 -05:00
Add YouTube plugin. Template adjustments
This commit is contained in:
parent
d523bc4603
commit
9d08c39a39
BIN
IMDb/.config.py.swp
Normal file
BIN
IMDb/.config.py.swp
Normal file
Binary file not shown.
@ -51,13 +51,11 @@ def configure(advanced):
|
|||||||
IMDb = conf.registerPlugin('IMDb')
|
IMDb = conf.registerPlugin('IMDb')
|
||||||
|
|
||||||
conf.registerGlobalValue(IMDb, 'template',
|
conf.registerGlobalValue(IMDb, 'template',
|
||||||
registry.String("\x02\x031,8 IMDb \x0F\x02 | $title ($year, $country, [$rated], $genre, $runtime) | IMDb: $imdbRating | MC: $metascore | RT: $tomatoMeter | http://imdb.com/title/$imdbID | $plot | Director: $director | Writer: $writer | Actors: $actors", _("""Template for the output of a search query.""")))
|
registry.String("\x02\x031,8 IMDb \x0F\x02 :: $title ($year, $country, [$rated], $genre, $runtime) :: IMDb: $imdbRating | MC: $metascore | RT: $tomatoMeter :: http://imdb.com/title/$imdbID :: $plot :: Director: $director :: Writer: $writer :: Actors: $actors", _("""Template for the output of a search query.""")))
|
||||||
|
|
||||||
# alternative template:
|
|
||||||
# $title ($year - $director) :: [i:$imdbRating r:$tomatoMeter m:$metascore] $plot :: http://imdb.com/title/$imdbID
|
|
||||||
|
|
||||||
conf.registerGlobalValue(IMDb, 'noResultsMessage',
|
conf.registerGlobalValue(IMDb, 'noResultsMessage',
|
||||||
registry.String("No results for that query.", _("""This message is sent when there are no results""")))
|
registry.String("No results for that query.", _("""This message is sent when there are no results""")))
|
||||||
|
|
||||||
conf.registerGlobalValue(IMDb, 'omdbAPI',
|
conf.registerGlobalValue(IMDb, 'omdbAPI',
|
||||||
registry.String('', _("""OMDB API Key""")))
|
registry.String('', _("""OMDB API Key""")))
|
||||||
|
|
||||||
|
@ -192,10 +192,10 @@ conf.registerGlobalValue(SpiffyTitles.youtube, 'developerKey',
|
|||||||
registry.String("", _("""Youtube developer key - required for Youtube handler."""), private=True))
|
registry.String("", _("""Youtube developer key - required for Youtube handler."""), private=True))
|
||||||
# YouTube Logo
|
# YouTube Logo
|
||||||
conf.registerChannelValue(SpiffyTitles.youtube, 'logo',
|
conf.registerChannelValue(SpiffyTitles.youtube, 'logo',
|
||||||
registry.String("\x030,4 ► \x031,0YouTube", _("""Logo used with {{yt_logo}} in template""")))
|
registry.String("\x02\x030,4 ► \x031,0YouTube", _("""Logo used with {{yt_logo}} in template""")))
|
||||||
# YouTube template
|
# YouTube template
|
||||||
conf.registerChannelValue(SpiffyTitles.youtube, 'template',
|
conf.registerChannelValue(SpiffyTitles.youtube, 'template',
|
||||||
registry.String("^ {{yt_logo}} :: {{title}} {%if timestamp%} @ {{timestamp}}{% endif %} :: Duration: {{duration}} :: Views: {{view_count}} uploaded by {{channel_title}} :: {{like_count}} likes :: {{dislike_count}} dislikes :: {{favorite_count}} favorites", _("""Template used for YouTube title responses""")))
|
registry.String("^ {{yt_logo}} :: {{title}} {%if timestamp%} @ {{timestamp}}{% endif %} :: Duration: {{duration}} :: Views: {{view_count}} :: Uploader {{channel_title}} :: {{like_count}} likes :: {{dislike_count}} dislikes :: {{favorite_count}} favorites :: {{comment_count}} comments", _("""Template used for YouTube title responses""")))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -247,7 +247,7 @@ conf.registerGlobalValue(SpiffyTitles.twitch, 'clientID',
|
|||||||
|
|
||||||
# Twitch Logo
|
# Twitch Logo
|
||||||
conf.registerChannelValue(SpiffyTitles.twitch, 'logo',
|
conf.registerChannelValue(SpiffyTitles.twitch, 'logo',
|
||||||
registry.String("\x030,6💬twitch", _("""Logo used with {{twitch_logo}} in template""")))
|
registry.String("\x02\x030,6💬twitch", _("""Logo used with {{twitch_logo}} in template""")))
|
||||||
|
|
||||||
conf.registerChannelValue(SpiffyTitles.twitch, 'channelTemplate',
|
conf.registerChannelValue(SpiffyTitles.twitch, 'channelTemplate',
|
||||||
registry.String("^ {{twitch_logo}} :: {{display_name}} {%if description%}:: {{description}} {%endif%}:: Viewers: {{view_count}}", _("""twitch.tv channel template""")))
|
registry.String("^ {{twitch_logo}} :: {{display_name}} {%if description%}:: {{description}} {%endif%}:: Viewers: {{view_count}}", _("""twitch.tv channel template""")))
|
||||||
@ -289,11 +289,11 @@ conf.registerGlobalValue(SpiffyTitles.imdb, 'omdbAPI',
|
|||||||
|
|
||||||
# IMDB Logo
|
# IMDB Logo
|
||||||
conf.registerChannelValue(SpiffyTitles.imdb, 'logo',
|
conf.registerChannelValue(SpiffyTitles.imdb, 'logo',
|
||||||
registry.String("\x031,8 IMDb ", _("""Logo used with {{imdb_logo}} in template""")))
|
registry.String("\x02\x031,8 IMDb ", _("""Logo used with {{imdb_logo}} in template""")))
|
||||||
|
|
||||||
# IMDB template
|
# IMDB template
|
||||||
conf.registerChannelValue(SpiffyTitles.imdb, 'template',
|
conf.registerChannelValue(SpiffyTitles.imdb, 'template',
|
||||||
registry.String("^ {{imdb_logo}} :: {{title}} ({{year}}, {{country}}, [{{rated}}], {{genre}}, {{runtime}}) :: IMDB: {{imdb_rating}} | MC: {{metascore}} | RT: {{tomatoMeter}} :: {{plot}}", _("""IMDB title template""")))
|
registry.String("^ {{imdb_logo}} :: {{title}} ({{year}}, {{country}}, [{{rated}}], {{genre}}, {{runtime}}) :: IMDb: {{imdb_rating}} | MC: {{metascore}} | RT: {{tomatoMeter}} :: {{plot}}", _("""IMDB title template""")))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,10 +37,6 @@ import re
|
|||||||
import requests
|
import requests
|
||||||
import urllib
|
import urllib
|
||||||
import sys
|
import sys
|
||||||
try:
|
|
||||||
from urllib import urlencode
|
|
||||||
from urlparse import urlparse, parse_qsl
|
|
||||||
except ImportError:
|
|
||||||
from urllib.parse import urlencode, urlparse, parse_qsl
|
from urllib.parse import urlencode, urlparse, parse_qsl
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
import random
|
import random
|
||||||
@ -1748,12 +1744,7 @@ class SpiffyTitles(callbacks.Plugin):
|
|||||||
"""
|
"""
|
||||||
Returns the requested template object.
|
Returns the requested template object.
|
||||||
"""
|
"""
|
||||||
if sys.version_info[0] >= 3:
|
template = Template(self.registryValue(handler_template, channel=channel))
|
||||||
template = Template(self.registryValue(handler_template,
|
|
||||||
channel=channel))
|
|
||||||
else:
|
|
||||||
template = Template(self.registryValue(handler_template,
|
|
||||||
channel=channel).decode("utf-8"))
|
|
||||||
return template
|
return template
|
||||||
|
|
||||||
Class = SpiffyTitles
|
Class = SpiffyTitles
|
||||||
|
3
YouTube/README.md
Normal file
3
YouTube/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Search for YouTube videos and return link + info. Search powered by Google.
|
||||||
|
|
||||||
|
`config plugins.youtube.developerkey <your_key_here>`
|
71
YouTube/__init__.py
Normal file
71
YouTube/__init__.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
###
|
||||||
|
# Copyright (c) 2015, butterscotchstallion
|
||||||
|
# Copyright (c) 2020, oddluck <oddluck@riseup.net>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
|
# this list of conditions, and the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
# this list of conditions, and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution.
|
||||||
|
# * Neither the name of the author of this software nor the name of
|
||||||
|
# contributors to this software may be used to endorse or promote products
|
||||||
|
# derived from this software without specific prior written consent.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
###
|
||||||
|
|
||||||
|
"""
|
||||||
|
YouTube: Queries OMDB database for information about YouTube titles
|
||||||
|
"""
|
||||||
|
|
||||||
|
import supybot
|
||||||
|
import supybot.world as world
|
||||||
|
|
||||||
|
# Use this for the version of this plugin. You may wish to put a CVS keyword
|
||||||
|
# in here if you're keeping the plugin in CVS or some similar system.
|
||||||
|
__version__ = "2020.02.24+git"
|
||||||
|
|
||||||
|
# XXX Replace this with an appropriate author or supybot.Author instance.
|
||||||
|
__author__ = supybot.Author('butterscotchstallion', 'butterscotchstallion',
|
||||||
|
'')
|
||||||
|
__maintainer__ = getattr(supybot.authors, 'oddluck',
|
||||||
|
supybot.Author('oddluck', 'oddluck', 'oddluck@riseup.net'))
|
||||||
|
|
||||||
|
# This is a dictionary mapping supybot.Author instances to lists of
|
||||||
|
# contributions.
|
||||||
|
__contributors__ = {}
|
||||||
|
|
||||||
|
# This is a url where the most recent plugin package can be downloaded.
|
||||||
|
__url__ = 'https://github.com/oddluck/limnoria-plugins/'
|
||||||
|
|
||||||
|
from . import config
|
||||||
|
from . import plugin
|
||||||
|
from imp import reload
|
||||||
|
# In case we're being reloaded.
|
||||||
|
reload(config)
|
||||||
|
reload(plugin)
|
||||||
|
# Add more reloads here if you add third-party modules and want them to be
|
||||||
|
# reloaded when this plugin is reloaded. Don't forget to import them as well!
|
||||||
|
|
||||||
|
if world.testing:
|
||||||
|
from . import test
|
||||||
|
|
||||||
|
Class = plugin.Class
|
||||||
|
configure = config.configure
|
||||||
|
|
||||||
|
|
||||||
|
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
|
67
YouTube/config.py
Normal file
67
YouTube/config.py
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
###
|
||||||
|
# Copyright (c) 2015, butterscotchstallion
|
||||||
|
# Copyright (c) 2020, oddluck <oddluck@riseup.net>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
|
# this list of conditions, and the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
# this list of conditions, and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution.
|
||||||
|
# * Neither the name of the author of this software nor the name of
|
||||||
|
# contributors to this software may be used to endorse or promote products
|
||||||
|
# derived from this software without specific prior written consent.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
###
|
||||||
|
|
||||||
|
import supybot.conf as conf
|
||||||
|
import supybot.registry as registry
|
||||||
|
try:
|
||||||
|
from supybot.i18n import PluginInternationalization
|
||||||
|
_ = PluginInternationalization('YouTube')
|
||||||
|
except:
|
||||||
|
# Placeholder that allows to run the plugin on a bot
|
||||||
|
# without the i18n module
|
||||||
|
_ = lambda x: x
|
||||||
|
|
||||||
|
|
||||||
|
def configure(advanced):
|
||||||
|
# This will be called by supybot to configure this module. advanced is
|
||||||
|
# a bool that specifies whether the user identified themself as an advanced
|
||||||
|
# user or not. You should effect your configuration by manipulating the
|
||||||
|
# registry as appropriate.
|
||||||
|
from supybot.questions import expect, anything, something, yn
|
||||||
|
conf.registerPlugin('YouTube', True)
|
||||||
|
|
||||||
|
|
||||||
|
YouTube = conf.registerPlugin('YouTube')
|
||||||
|
|
||||||
|
|
||||||
|
conf.registerGlobalValue(YouTube, 'developerKey',
|
||||||
|
registry.String("", _("""Google API key. Required.""")))
|
||||||
|
|
||||||
|
conf.registerChannelValue(YouTube, 'logo',
|
||||||
|
registry.String("\x02\x030,4 ► \x031,0YouTube", _("""Logo used with $yt_logo in template""")))
|
||||||
|
|
||||||
|
conf.registerChannelValue(YouTube, 'template',
|
||||||
|
registry.String("{{logo}} :: {{link}} :: {{title}} :: Duration: {{duration}} :: Views: {{views}} :: Uploader: {{uploader}} :: {{likes}} likes :: {{dislikes}} dislikes :: {{favorites}} favorites :: {{comments}} comments", _("""Template used for search result replies""")))
|
||||||
|
|
||||||
|
conf.registerChannelValue(YouTube, 'useBold',
|
||||||
|
registry.Boolean(True, _("""Use bold in replies""")))
|
||||||
|
|
||||||
|
|
||||||
|
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
|
269
YouTube/plugin.py
Normal file
269
YouTube/plugin.py
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
###
|
||||||
|
# Copyright (c) 2015, butterscotchstallion
|
||||||
|
# Copyright (c) 2020, oddluck <oddluck@riseup.net>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
|
# this list of conditions, and the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
# this list of conditions, and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution.
|
||||||
|
# * Neither the name of the author of this software nor the name of
|
||||||
|
# contributors to this software may be used to endorse or promote products
|
||||||
|
# derived from this software without specific prior written consent.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
###
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import supybot.utils as utils
|
||||||
|
from supybot.commands import *
|
||||||
|
import supybot.plugins as plugins
|
||||||
|
import supybot.ircutils as ircutils
|
||||||
|
import supybot.ircmsgs as ircmsgs
|
||||||
|
import supybot.callbacks as callbacks
|
||||||
|
import supybot.log as log
|
||||||
|
import requests
|
||||||
|
import pendulum
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
from jinja2 import Template
|
||||||
|
from fake_useragent import UserAgent
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
from urllib.parse import urlencode, urlparse, parse_qsl
|
||||||
|
|
||||||
|
try:
|
||||||
|
from supybot.i18n import PluginInternationalization
|
||||||
|
_ = PluginInternationalization('YouTube')
|
||||||
|
except ImportError:
|
||||||
|
# Placeholder that allows to run the plugin on a bot
|
||||||
|
# without the i18n module
|
||||||
|
_ = lambda x: x
|
||||||
|
|
||||||
|
class YouTube(callbacks.Plugin):
|
||||||
|
"""Queries OMDB database for information about YouTube titles"""
|
||||||
|
threaded = True
|
||||||
|
|
||||||
|
def dosearch(self, query):
|
||||||
|
try:
|
||||||
|
searchurl = "https://www.google.com/search?&q={0} site:youtube.com".format(query)
|
||||||
|
ua = UserAgent()
|
||||||
|
header = {'User-Agent':str(ua.random)}
|
||||||
|
data = requests.get(searchurl, headers=header)
|
||||||
|
soup = BeautifulSoup(data.text)
|
||||||
|
elements = soup.select('.r a')
|
||||||
|
url = elements[0]['href']
|
||||||
|
url = re.split('https?://', url)[-1]
|
||||||
|
url = re.sub("&rct=.*", "", url)
|
||||||
|
url = "https://{0}".format(url)
|
||||||
|
except Exception:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
return url
|
||||||
|
|
||||||
|
def get_video_id_from_url(self, url):
|
||||||
|
"""
|
||||||
|
Get YouTube video ID from URL
|
||||||
|
"""
|
||||||
|
info = urlparse(url)
|
||||||
|
try:
|
||||||
|
path = info.path
|
||||||
|
domain = info.netloc
|
||||||
|
video_id = ""
|
||||||
|
|
||||||
|
if domain == "youtu.be":
|
||||||
|
video_id = path.split("/")[1]
|
||||||
|
else:
|
||||||
|
parsed = parse_qsl(info.query)
|
||||||
|
params = dict(parsed)
|
||||||
|
|
||||||
|
if "v" in params:
|
||||||
|
video_id = params["v"]
|
||||||
|
|
||||||
|
if video_id:
|
||||||
|
return video_id
|
||||||
|
else:
|
||||||
|
log.error("SpiffyTitles: error getting video id from %s" % (url))
|
||||||
|
return None
|
||||||
|
|
||||||
|
except IndexError as e:
|
||||||
|
log.error("SpiffyTitles: error getting video id from %s (%s)" % (url, str(e)))
|
||||||
|
|
||||||
|
def get_duration_from_seconds(self, duration_seconds):
|
||||||
|
m, s = divmod(duration_seconds, 60)
|
||||||
|
h, m = divmod(m, 60)
|
||||||
|
|
||||||
|
duration = "%02d:%02d" % (m, s)
|
||||||
|
|
||||||
|
""" Only include hour if the video is at least 1 hour long """
|
||||||
|
if h > 0:
|
||||||
|
duration = "%02d:%s" % (h, duration)
|
||||||
|
|
||||||
|
return duration
|
||||||
|
|
||||||
|
def get_total_seconds_from_duration(self, input):
|
||||||
|
"""
|
||||||
|
Duration comes in a format like this: PT4M41S which translates to
|
||||||
|
4 minutes and 41 seconds. This method returns the total seconds
|
||||||
|
so that the duration can be parsed as usual.
|
||||||
|
"""
|
||||||
|
regex = re.compile("""
|
||||||
|
(?P<sign> -?) P
|
||||||
|
(?:(?P<years> \d+) Y)?
|
||||||
|
(?:(?P<months> \d+) M)?
|
||||||
|
(?:(?P<days> \d+) D)?
|
||||||
|
(?: T
|
||||||
|
(?:(?P<hours> \d+) H)?
|
||||||
|
(?:(?P<minutes>\d+) M)?
|
||||||
|
(?:(?P<seconds>\d+) S)?
|
||||||
|
)?
|
||||||
|
""", re.VERBOSE)
|
||||||
|
duration = regex.match(input).groupdict(0)
|
||||||
|
|
||||||
|
delta = pendulum.duration(hours=int(duration['hours']),
|
||||||
|
minutes=int(duration['minutes']),
|
||||||
|
seconds=int(duration['seconds']))
|
||||||
|
|
||||||
|
return delta.total_seconds()
|
||||||
|
|
||||||
|
def get_youtube_logo(self):
|
||||||
|
use_bold = self.registryValue("useBold", dynamic.channel)
|
||||||
|
if use_bold:
|
||||||
|
yt_logo = "{0}\x0F\x02".format(self.registryValue("logo", dynamic.channel))
|
||||||
|
else:
|
||||||
|
yt_logo = "{0}\x0F".format(self.registryValue("logo", dynamic.channel))
|
||||||
|
|
||||||
|
return yt_logo
|
||||||
|
|
||||||
|
def yt(self, irc, msg, args, query):
|
||||||
|
"""<search term>
|
||||||
|
Search for YouTube videos
|
||||||
|
"""
|
||||||
|
apikey = self.registryValue('developerKey')
|
||||||
|
url = self.dosearch(query)
|
||||||
|
if url:
|
||||||
|
video_id = self.get_video_id_from_url(url)
|
||||||
|
else:
|
||||||
|
video_id = None
|
||||||
|
irc.reply("No results found for {0}".format(query))
|
||||||
|
return
|
||||||
|
|
||||||
|
channel = msg.args[0]
|
||||||
|
result = None
|
||||||
|
ua = UserAgent()
|
||||||
|
headers = {'User-Agent':str(ua.random)}
|
||||||
|
|
||||||
|
yt_template = Template(self.registryValue("template", dynamic.channel))
|
||||||
|
title = ""
|
||||||
|
|
||||||
|
if video_id:
|
||||||
|
log.debug("YouTube: got video id: %s" % video_id)
|
||||||
|
options = {
|
||||||
|
"part": "snippet,statistics,contentDetails",
|
||||||
|
"maxResults": 1,
|
||||||
|
"key": apikey,
|
||||||
|
"id": video_id
|
||||||
|
}
|
||||||
|
encoded_options = urlencode(options)
|
||||||
|
api_url = "https://www.googleapis.com/youtube/v3/videos?%s" % (encoded_options)
|
||||||
|
|
||||||
|
log.debug("YouTube: requesting %s" % (api_url))
|
||||||
|
|
||||||
|
request = requests.get(api_url, headers=headers)
|
||||||
|
ok = request.status_code == requests.codes.ok
|
||||||
|
|
||||||
|
if ok:
|
||||||
|
response = json.loads(request.text)
|
||||||
|
|
||||||
|
if response:
|
||||||
|
try:
|
||||||
|
if response["pageInfo"]["totalResults"] > 0:
|
||||||
|
items = response["items"]
|
||||||
|
video = items[0]
|
||||||
|
snippet = video["snippet"]
|
||||||
|
title = snippet["title"]
|
||||||
|
statistics = video["statistics"]
|
||||||
|
view_count = 0
|
||||||
|
like_count = 0
|
||||||
|
dislike_count = 0
|
||||||
|
comment_count = 0
|
||||||
|
favorite_count = 0
|
||||||
|
|
||||||
|
if "viewCount" in statistics:
|
||||||
|
view_count = "{:,}".format(int(statistics["viewCount"]))
|
||||||
|
|
||||||
|
if "likeCount" in statistics:
|
||||||
|
like_count = "{:,}".format(int(statistics["likeCount"]))
|
||||||
|
|
||||||
|
if "dislikeCount" in statistics:
|
||||||
|
dislike_count = "{:,}".format(int(statistics["dislikeCount"]))
|
||||||
|
|
||||||
|
if "favoriteCount" in statistics:
|
||||||
|
favorite_count = "{:,}".format(int(statistics["favoriteCount"]))
|
||||||
|
|
||||||
|
if "commentCount" in statistics:
|
||||||
|
comment_count = "{:,}".format(int(statistics["commentCount"]))
|
||||||
|
|
||||||
|
channel_title = snippet["channelTitle"]
|
||||||
|
video_duration = video["contentDetails"]["duration"]
|
||||||
|
duration_seconds = self.get_total_seconds_from_duration(video_duration)
|
||||||
|
|
||||||
|
"""
|
||||||
|
#23 - If duration is zero, then it"s a LIVE video
|
||||||
|
"""
|
||||||
|
if duration_seconds > 0:
|
||||||
|
duration = self.get_duration_from_seconds(duration_seconds)
|
||||||
|
else:
|
||||||
|
duration = "LIVE"
|
||||||
|
|
||||||
|
yt_logo = self.get_youtube_logo()
|
||||||
|
|
||||||
|
link = "https://youtu.be/%s" % (video_id)
|
||||||
|
|
||||||
|
compiled_template = yt_template.render({
|
||||||
|
"title": title,
|
||||||
|
"duration": duration,
|
||||||
|
"views": view_count,
|
||||||
|
"likes": like_count,
|
||||||
|
"dislikes": dislike_count,
|
||||||
|
"comments": comment_count,
|
||||||
|
"favorites": favorite_count,
|
||||||
|
"uploader": channel_title,
|
||||||
|
"link": link,
|
||||||
|
"logo": yt_logo
|
||||||
|
})
|
||||||
|
|
||||||
|
title = compiled_template
|
||||||
|
else:
|
||||||
|
log.debug("YouTube: video appears to be private; no results!")
|
||||||
|
|
||||||
|
except IndexError as e:
|
||||||
|
log.error("YouTube: IndexError parsing Youtube API JSON response: %s" %
|
||||||
|
(str(e)))
|
||||||
|
else:
|
||||||
|
log.error("YouTube: Error parsing Youtube API JSON response")
|
||||||
|
else:
|
||||||
|
log.error("YouTube: YouTube API HTTP %s: %s" %
|
||||||
|
(request.status_code, request.text))
|
||||||
|
if title:
|
||||||
|
irc.reply(title, prefixNick=False)
|
||||||
|
|
||||||
|
yt = wrap(yt, ['text'])
|
||||||
|
|
||||||
|
Class = YouTube
|
||||||
|
|
||||||
|
|
||||||
|
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
Loading…
x
Reference in New Issue
Block a user