Upload Plex posters to Imgur for notifications

This commit is contained in:
JonnyWong16 2016-02-19 23:25:33 -08:00
parent eab6365af9
commit 284ab45a17
4 changed files with 93 additions and 171 deletions

View file

@ -1,107 +0,0 @@
'''OpenAnything: a kind and thoughtful library for HTTP web services
This program is part of 'Dive Into Python', a free Python book for
experienced programmers. Visit http://diveintopython.org/ for the
latest version.
'''
__author__ = 'Mark Pilgrim (mark@diveintopython.org)'
__version__ = '$Revision: 1.6 $'[11:-2]
__date__ = '$Date: 2004/04/16 21:16:24 $'
__copyright__ = 'Copyright (c) 2004 Mark Pilgrim'
__license__ = 'Python'
import urllib2, urlparse, gzip
from StringIO import StringIO
USER_AGENT = 'OpenAnything/%s +http://diveintopython.org/http_web_services/' % __version__
class SmartRedirectHandler(urllib2.HTTPRedirectHandler):
def http_error_301(self, req, fp, code, msg, headers):
result = urllib2.HTTPRedirectHandler.http_error_301(
self, req, fp, code, msg, headers)
result.status = code
return result
def http_error_302(self, req, fp, code, msg, headers):
result = urllib2.HTTPRedirectHandler.http_error_302(
self, req, fp, code, msg, headers)
result.status = code
return result
class DefaultErrorHandler(urllib2.HTTPDefaultErrorHandler):
def http_error_default(self, req, fp, code, msg, headers):
result = urllib2.HTTPError(
req.get_full_url(), code, msg, headers, fp)
result.status = code
return result
def openAnything(source, etag=None, lastmodified=None, agent=USER_AGENT):
"""URL, filename, or string --> stream
This function lets you define parsers that take any input source
(URL, pathname to local or network file, or actual data as a string)
and deal with it in a uniform manner. Returned object is guaranteed
to have all the basic stdio read methods (read, readline, readlines).
Just .close() the object when you're done with it.
If the etag argument is supplied, it will be used as the value of an
If-None-Match request header.
If the lastmodified argument is supplied, it must be a formatted
date/time string in GMT (as returned in the Last-Modified header of
a previous request). The formatted date/time will be used
as the value of an If-Modified-Since request header.
If the agent argument is supplied, it will be used as the value of a
User-Agent request header.
"""
if hasattr(source, 'read'):
return source
if source == '-':
return sys.stdin
if urlparse.urlparse(source)[0] == 'http':
# open URL with urllib2
request = urllib2.Request(source)
request.add_header('User-Agent', agent)
if lastmodified:
request.add_header('If-Modified-Since', lastmodified)
if etag:
request.add_header('If-None-Match', etag)
request.add_header('Accept-encoding', 'gzip')
opener = urllib2.build_opener(SmartRedirectHandler(), DefaultErrorHandler())
return opener.open(request)
# try to open with native open function (if source is a filename)
try:
return open(source)
except (IOError, OSError):
pass
# treat source as string
return StringIO(str(source))
def fetch(source, etag=None, lastmodified=None, agent=USER_AGENT):
'''Fetch data and metadata from a URL, file, stream, or string'''
result = {}
f = openAnything(source, etag, lastmodified, agent)
result['data'] = f.read()
if hasattr(f, 'headers'):
# save ETag, if the server sent one
result['etag'] = f.headers.get('ETag')
# save Last-Modified header, if the server sent one
result['lastmodified'] = f.headers.get('Last-Modified')
if f.headers.get('content-encoding') == 'gzip':
# data came back gzip-compressed, decompress it
result['data'] = gzip.GzipFile(fileobj=StringIO(result['data'])).read()
if hasattr(f, 'url'):
result['url'] = f.url
result['status'] = 200
if hasattr(f, 'status'):
result['status'] = f.status
f.close()
return result

View file

@ -13,23 +13,25 @@
# You should have received a copy of the GNU General Public License
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
from IPy import IP
import base64
import datetime
import fnmatch
from functools import wraps
from IPy import IP
import json
import os
import math
from operator import itemgetter
import os
import re
import shutil
import socket
import sys
import time
from xml.dom import minidom
import unicodedata
import urllib, urllib2
from xml.dom import minidom
import xmltodict
import plexpy
from api2 import API2
@ -523,3 +525,37 @@ def anon_url(*url):
Return a URL string consisting of the Anonymous redirect URL and an arbitrary number of values appended.
"""
return '' if None in url else '%s%s' % (plexpy.CONFIG.ANON_REDIRECT, ''.join(str(s) for s in url))
def uploadToImgur(imgPath, imgTitle=''):
from plexpy import logger
client_id = '743b1a443ccd2b0'
img_url = ''
try:
with open(imgPath, 'rb') as imgFile:
img = imgFile.read()
except IOError as e:
logger.error(u"PlexPy Helpers :: Unable to read image file for Imgur: %s" % e)
return img_url
headers = {'Authorization': 'Client-ID %s' % client_id}
data = {'type': 'base64',
'image': base64.b64encode(img)}
if imgTitle:
data['title'] = imgTitle
data['name'] = imgTitle + '.jpg'
request = urllib2.Request('https://api.imgur.com/3/image', headers=headers, data=urllib.urlencode(data))
response = urllib2.urlopen(request)
response = json.loads(response.read())
if response.get('status') == 200:
logger.debug(u"PlexPy Helpers :: Image uploaded to Imgur.")
img_url = response.get('data').get('link', '')
elif response.get('status') >= 400 and response.get('status') < 500:
logger.warn(u"PlexPy Helpers :: Unable to upload image to Imgur: %s" % response.reason)
else:
logger.warn(u"PlexPy Helpers :: Unable to upload image to Imgur.")
return img_url

View file

@ -15,12 +15,10 @@
import arrow
import json
from httplib import HTTPConnection
import openanything
import os
import re
import time
import urllib2
import urllib
from plexpy import logger, config, notifiers, database, helpers, plextv, pmsconnect
import plexpy
@ -157,7 +155,8 @@ def notify(stream_data=None, notify_action=None):
subject=notify_strings[0],
body=notify_strings[1],
notify_action=notify_action,
script_args=notify_strings[2])
script_args=notify_strings[2],
metadata=notify_strings[3])
# Set the notification state in the db
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
@ -169,7 +168,8 @@ def notify(stream_data=None, notify_action=None):
subject=notify_strings[0],
body=notify_strings[1],
notify_action=notify_action,
script_args=notify_strings[2])
script_args=notify_strings[2],
metadata=notify_strings[3])
# Set the notification state in the db
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
@ -181,7 +181,8 @@ def notify(stream_data=None, notify_action=None):
subject=notify_strings[0],
body=notify_strings[1],
notify_action=notify_action,
script_args=notify_strings[2])
script_args=notify_strings[2],
metadata=notify_strings[3])
# Set the notification state in the db
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
@ -193,7 +194,8 @@ def notify(stream_data=None, notify_action=None):
subject=notify_strings[0],
body=notify_strings[1],
notify_action=notify_action,
script_args=notify_strings[2])
script_args=notify_strings[2],
metadata=notify_strings[3])
# Set the notification state in the db
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
@ -205,7 +207,8 @@ def notify(stream_data=None, notify_action=None):
subject=notify_strings[0],
body=notify_strings[1],
notify_action=notify_action,
script_args=notify_strings[2])
script_args=notify_strings[2],
metadata=notify_strings[3])
# Set the notification state in the db
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
@ -499,46 +502,21 @@ def build_notify_text(session=None, timeline=None, state=None):
metadata['lastfm_id'] = metadata['guid'].split('lastfm://')[1].rsplit('/', 1)[0]
metadata['lastfm_url'] = 'https://www.last.fm/music/' + metadata['lastfm_id']
# Get posters (only IMDB and TheTVDB supported)
if metadata['media_type'] == 'movie' and metadata.get('imdb_id', ''):
uri = '/?i=' + metadata['imdb_id']
if metadata['media_type'] == 'movie' or metadata['media_type'] == 'show' or metadata['media_type'] == 'artist':
thumb = metadata['thumb']
elif metadata['media_type'] == 'episode':
thumb = metadata['grandparent_thumb']
elif metadata['media_type'] == 'track':
thumb = metadata['parent_thumb']
else:
thumb = None
# Get poster using OMDb API
http_handler = HTTPConnection("www.omdbapi.com")
http_handler.request('GET', uri)
response = http_handler.getresponse()
request_status = response.status
if request_status == 200:
data = json.loads(response.read())
poster_url = data.get('Poster', '')
metadata['poster_url'] = poster_url if poster_url != 'N/A' else ''
elif request_status >= 400 and request_status < 500:
logger.warn(u"PlexPy Notifiers :: Unable to retrieve IMDB poster: %s" % response.reason)
else:
logger.warn(u"PlexPy Notifiers :: Unable to retrieve IMDB poster.")
elif (metadata['media_type'] == 'show' or metadata['media_type'] == 'episode') \
and (metadata.get('imdb_id', '') or metadata.get('thetvdb_id', '')):
if metadata.get('imdb_id', ''):
uri = '/lookup/shows?imdb=' + metadata['imdb_id']
elif metadata.get('thetvdb_id', ''):
uri = '/lookup/shows?thetvdb=' + metadata['thetvdb_id']
# Get poster using TVmaze API
request = urllib2.Request('http://api.tvmaze.com' + uri)
opener = urllib2.build_opener(openanything.SmartRedirectHandler())
response = opener.open(request)
request_status = response.status
if request_status == 301:
data = json.loads(response.read())
image = data.get('image', '')
metadata['poster_url'] = image.get('original', image.get('medium',''))
elif request_status >= 400 and request_status < 500:
logger.warn(u"PlexPy Notifiers :: Unable to retrieve TVmaze poster: %s" % response.reason)
else:
logger.warn(u"PlexPy Notifiers :: Unable to retrieve TVmaze poster.")
if thumb:
# Retrieve the poster from Plex and cache to file
urllib.urlretrieve(plexpy.CONFIG.PMS_URL + thumb + '?X-Plex-Token=' + plexpy.CONFIG.PMS_TOKEN,
os.path.join(plexpy.CONFIG.CACHE_DIR, 'cache-poster.jpg'))
# Upload thumb to Imgur and get link
metadata['poster_url'] = helpers.uploadToImgur(os.path.join(plexpy.CONFIG.CACHE_DIR, 'cache-poster.jpg'), full_title)
# Fix metadata params for notify recently added grandparent
if state == 'created' and plexpy.CONFIG.NOTIFY_RECENTLY_ADDED_GRANDPARENT:

View file

@ -19,8 +19,7 @@ import json
import cherrypy
from email.mime.text import MIMEText
import email.utils
from httplib import HTTPSConnection, HTTPConnection
import openanything
from httplib import HTTPSConnection
import os
import shlex
import smtplib
@ -2129,19 +2128,35 @@ class FacebookNotifier(object):
if self.incl_poster and 'metadata' in kwargs:
metadata = kwargs['metadata']
poster_url = metadata.get('poster_url','')
caption = 'View in Plex Web.'
if metadata['media_type'] == 'movie' or metadata['media_type'] == 'show':
title = metadata['title']
subtitle = metadata['year']
elif metadata['media_type'] == 'episode':
title = metadata['grandparent_title'] + ' - ' + metadata['title']
subtitle = 'S' + metadata['parent_media_index'] + ' ' + '\xc2\xb7'.decode('utf8') + \
' E' + metadata['media_index']
if poster_url:
if metadata['media_type'] == 'movie' or metadata['media_type'] == 'show':
title = metadata['title']
subtitle = metadata['year']
rating_key = metadata['rating_key']
elif metadata['media_type'] == 'episode':
title = '%s - %s' % (metadata['grandparent_title'], metadata['title'])
subtitle = 'S%s %s E%s' % (metadata['parent_media_index'],
'\xc2\xb7'.decode('utf8'),
metadata['media_index'])
rating_key = metadata['rating_key']
elif metadata['media_type'] == 'artist':
title = metadata['title']
subtitle = ''
rating_key = metadata['rating_key']
elif metadata['media_type'] == 'track':
title = '%s - %s' % (metadata['grandparent_title'], metadata['title'])
subtitle = metadata['parent_title']
rating_key = metadata['parent_rating_key']
caption = 'View in Plex Web.'
# Build Facebook post attachment
attachment['link'] = 'http://app.plex.tv/web/app#!/server/' + plexpy.CONFIG.PMS_IDENTIFIER + \
'/details/%2Flibrary%2Fmetadata%2F' + metadata['rating_key']
'/details/%2Flibrary%2Fmetadata%2F' + rating_key
attachment['picture'] = poster_url
attachment['name'] = title
attachment['description'] = subtitle