Removed some facebook stuff, maybe adding it back later

This commit is contained in:
2021-02-05 18:16:12 +01:00
parent 1df28243c3
commit 91e28df1a5
13 changed files with 219 additions and 1481 deletions

View File

@@ -17,26 +17,29 @@
import base64
import bleach
import json
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import email.utils
from paho.mqtt.publish import single
import json
import os
import re
import requests
import smtplib
import subprocess
import sys
import threading
import time
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from urllib.parse import urlencode, urlparse
import bleach
import requests
from paho.mqtt.publish import single
try:
from Cryptodome.Protocol.KDF import PBKDF2
from Cryptodome.Cipher import AES
from Cryptodome.Random import get_random_bytes
from Cryptodome.Hash import HMAC, SHA1
CRYPTODOME = True
except ImportError:
try:
@@ -44,34 +47,23 @@ except ImportError:
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Hash import HMAC, SHA1
CRYPTODOME = True
except ImportError:
CRYPTODOME = False
import gntp.notifier
import facebook
import twitter
import jellypy
if jellypy.PYTHON2:
import common
import database
import helpers
import logger
import mobile_app
import pmsconnect
import request
import users
else:
from jellypy import common
from jellypy import database
from jellypy import helpers
from jellypy import logger
from jellypy import mobile_app
from jellypy import pmsconnect
from jellypy import request
from jellypy import users
from jellypy import common
from jellypy import database
from jellypy import helpers
from jellypy import logger
from jellypy import mobile_app
from jellypy import pmsconnect
from jellypy import request
from jellypy import users
BROWSER_NOTIFIERS = {}
@@ -135,12 +127,6 @@ def available_notification_agents():
'class': EMAIL,
'action_types': ('all',)
},
{'label': 'Facebook',
'name': 'facebook',
'id': AGENT_IDS['facebook'],
'class': FACEBOOK,
'action_types': ('all',)
},
{'label': 'GroupMe',
'name': 'groupme',
'id': AGENT_IDS['groupme'],
@@ -788,7 +774,7 @@ class PrettyMetadata(object):
@staticmethod
def get_parameters():
parameters = {param['value']: param['name']
for category in common.NOTIFICATION_PARAMETERS for param in category['parameters']}
for category in common.NOTIFICATION_PARAMETERS for param in category['parameters']}
parameters[''] = ''
return parameters
@@ -852,7 +838,8 @@ class Notifier(object):
if response is not None and 400 <= response.status_code < 500:
verify_msg = " Verify your notification agent settings are correct."
logger.error("Tautulli Notifiers :: {name} notification failed.{msg}".format(msg=verify_msg, name=self.NAME))
logger.error(
"Tautulli Notifiers :: {name} notification failed.{msg}".format(msg=verify_msg, name=self.NAME))
if err_msg:
logger.error("Tautulli Notifiers :: {}".format(err_msg))
@@ -907,7 +894,7 @@ class ANDROIDAPP(Notifier):
'rating_key': pretty_metadata.parameters.get('rating_key', ''),
'poster_thumb': pretty_metadata.parameters.get('poster_thumb', '')}
#logger.debug("Plaintext data: {}".format(plaintext_data))
# logger.debug("Plaintext data: {}".format(plaintext_data))
if CRYPTODOME:
# Key generation
@@ -918,7 +905,7 @@ class ANDROIDAPP(Notifier):
key = PBKDF2(passphrase, salt, dkLen=key_length, count=iterations,
prf=lambda p, s: HMAC.new(p, s, SHA1).digest())
#logger.debug("Encryption key (base64): {}".format(base64.b64encode(key)))
# logger.debug("Encryption key (base64): {}".format(base64.b64encode(key)))
# Encrypt using AES GCM
nonce = get_random_bytes(16)
@@ -926,10 +913,10 @@ class ANDROIDAPP(Notifier):
encrypted_data, gcm_tag = cipher.encrypt_and_digest(json.dumps(plaintext_data).encode('utf-8'))
encrypted_data += gcm_tag
#logger.debug("Encrypted data (base64): {}".format(base64.b64encode(encrypted_data)))
#logger.debug("GCM tag (base64): {}".format(base64.b64encode(gcm_tag)))
#logger.debug("Nonce (base64): {}".format(base64.b64encode(nonce)))
#logger.debug("Salt (base64): {}".format(base64.b64encode(salt)))
# logger.debug("Encrypted data (base64): {}".format(base64.b64encode(encrypted_data)))
# logger.debug("GCM tag (base64): {}".format(base64.b64encode(gcm_tag)))
# logger.debug("Nonce (base64): {}".format(base64.b64encode(nonce)))
# logger.debug("Salt (base64): {}".format(base64.b64encode(salt)))
payload = {'app_id': mobile_app._ONESIGNAL_APP_ID,
'include_player_ids': [device['onesignal_id']],
@@ -953,7 +940,7 @@ class ANDROIDAPP(Notifier):
'server_id': jellypy.CONFIG.PMS_UUID}
}
#logger.debug("OneSignal payload: {}".format(payload))
# logger.debug("OneSignal payload: {}".format(payload))
headers = {'Content-Type': 'application/json'}
@@ -990,24 +977,25 @@ class ANDROIDAPP(Notifier):
'Please install the library to encrypt the notification contents. '
'Instructions can be found in the '
'<a href="' + helpers.anon_url(
'https://github.com/%s/%s-Wiki/wiki/Frequently-Asked-Questions#notifications-pycryptodome'
% (jellypy.CONFIG.GIT_USER, jellypy.CONFIG.GIT_REPO)) + '" target="_blank">FAQ</a>.' ,
'https://github.com/%s/%s-Wiki/wiki/Frequently-Asked-Questions#notifications-pycryptodome'
% (jellypy.CONFIG.GIT_USER, jellypy.CONFIG.GIT_REPO)) + '" target="_blank">FAQ</a>.',
'input_type': 'help'
})
})
else:
config_option.append({
'label': 'Note',
'description': 'The PyCryptodome library was found. '
'The content of your notifications will be sent encrypted!',
'input_type': 'help'
})
})
config_option[-1]['description'] += '<br><br>Notifications are sent using the ' \
'<a href="' + helpers.anon_url('https://onesignal.com') + '" target="_blank">' \
'OneSignal</a>. Some user data is collected and cannot be encrypted. ' \
'Please read the <a href="' + helpers.anon_url(
'https://onesignal.com/privacy_policy') + '" target="_blank">' \
'OneSignal Privacy Policy</a> for more details.'
'<a href="' + helpers.anon_url(
'https://onesignal.com') + '" target="_blank">' \
'OneSignal</a>. Some user data is collected and cannot be encrypted. ' \
'Please read the <a href="' + helpers.anon_url(
'https://onesignal.com/privacy_policy') + '" target="_blank">' \
'OneSignal Privacy Policy</a> for more details.'
devices = self.get_devices()
@@ -1018,7 +1006,7 @@ class ANDROIDAPP(Notifier):
'<a data-tab-destination="android_app" data-toggle="tab" data-dismiss="modal">'
'Get the Android App</a> and register a device.',
'input_type': 'help'
})
})
else:
config_option.append({
'label': 'Device',
@@ -1029,7 +1017,7 @@ class ANDROIDAPP(Notifier):
'register a new device</a> with Tautulli.',
'input_type': 'select',
'select_options': devices
})
})
config_option.append({
'label': 'Priority',
@@ -1038,7 +1026,7 @@ class ANDROIDAPP(Notifier):
'description': 'Set the notification priority.',
'input_type': 'select',
'select_options': {1: 'Minimum', 2: 'Low', 3: 'Normal', 4: 'High'}
})
})
return config_option
@@ -1081,7 +1069,7 @@ class BOXCAR(Notifier):
'flourish': 'Flourish',
'harp': 'Harp',
'light': 'Light',
'magic-chime':'Magic Chime',
'magic-chime': 'Magic Chime',
'magic-coin': 'Magic Coin',
'no-sound': 'No Sound',
'notifier-1': 'Notifier (1)',
@@ -1507,191 +1495,6 @@ class EMAIL(Notifier):
return config_option
class FACEBOOK(Notifier):
"""
Facebook notifications
"""
NAME = 'Facebook'
_DEFAULT_CONFIG = {'redirect_uri': '',
'access_token': '',
'app_id': '',
'app_secret': '',
'group_id': '',
'incl_subject': 1,
'incl_card': 0,
'movie_provider': '',
'tv_provider': '',
'music_provider': ''
}
def _get_authorization(self, app_id='', app_secret='', redirect_uri=''):
# Temporarily store settings in the config so we can retrieve them in Facebook step 2.
# Assume the user won't be requesting authorization for multiple Facebook notifiers at the same time.
jellypy.CONFIG.FACEBOOK_APP_ID = app_id
jellypy.CONFIG.FACEBOOK_APP_SECRET = app_secret
jellypy.CONFIG.FACEBOOK_REDIRECT_URI = redirect_uri
jellypy.CONFIG.FACEBOOK_TOKEN = 'temp'
return facebook.auth_url(app_id=app_id,
canvas_url=redirect_uri,
perms=['publish_to_groups'])
def _get_credentials(self, code=''):
logger.info("Tautulli Notifiers :: Requesting access token from {name}.".format(name=self.NAME))
app_id = jellypy.CONFIG.FACEBOOK_APP_ID
app_secret = jellypy.CONFIG.FACEBOOK_APP_SECRET
redirect_uri = jellypy.CONFIG.FACEBOOK_REDIRECT_URI
try:
# Request user access token
api = facebook.GraphAPI(version='2.12')
response = api.get_access_token_from_code(code=code,
redirect_uri=redirect_uri,
app_id=app_id,
app_secret=app_secret)
access_token = response['access_token']
# Request extended user access token
api = facebook.GraphAPI(access_token=access_token, version='2.12')
response = api.extend_access_token(app_id=app_id,
app_secret=app_secret)
jellypy.CONFIG.FACEBOOK_TOKEN = response['access_token']
except Exception as e:
logger.error("Tautulli Notifiers :: Error requesting {name} access token: {e}".format(name=self.NAME, e=e))
jellypy.CONFIG.FACEBOOK_TOKEN = ''
# Clear out temporary config values
jellypy.CONFIG.FACEBOOK_APP_ID = ''
jellypy.CONFIG.FACEBOOK_APP_SECRET = ''
jellypy.CONFIG.FACEBOOK_REDIRECT_URI = ''
return jellypy.CONFIG.FACEBOOK_TOKEN
def _post_facebook(self, **data):
if self.config['group_id']:
api = facebook.GraphAPI(access_token=self.config['access_token'], version='2.12')
try:
api.put_object(parent_object=self.config['group_id'], connection_name='feed', **data)
logger.info("Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME))
return True
except Exception as e:
logger.error("Tautulli Notifiers :: Error sending {name} post: {e}".format(name=self.NAME, e=e))
return False
else:
logger.error("Tautulli Notifiers :: Error sending {name} post: No {name} Group ID provided.".format(name=self.NAME))
return False
def agent_notify(self, subject='', body='', action='', **kwargs):
if self.config['incl_subject']:
text = subject + '\r\n' + body
else:
text = body
data = {'message': text}
if self.config['incl_card'] and kwargs.get('parameters', {}).get('media_type'):
# Grab formatted metadata
pretty_metadata = PrettyMetadata(kwargs['parameters'])
if pretty_metadata.media_type == 'movie':
provider = self.config['movie_provider']
elif pretty_metadata.media_type in ('show', 'season', 'episode'):
provider = self.config['tv_provider']
elif pretty_metadata.media_type in ('artist', 'album', 'track'):
provider = self.config['music_provider']
else:
provider = None
data['link'] = pretty_metadata.get_provider_link(provider)
return self._post_facebook(**data)
def _return_config_options(self):
config_option = [{'label': 'OAuth Redirect URI',
'value': self.config['redirect_uri'],
'name': 'facebook_redirect_uri',
'description': 'Fill in this address for the "Valid OAuth redirect URIs" '
'in your Facebook App.',
'input_type': 'text'
},
{'label': 'Facebook App ID',
'value': self.config['app_id'],
'name': 'facebook_app_id',
'description': 'Your Facebook app ID.',
'input_type': 'text'
},
{'label': 'Facebook App Secret',
'value': self.config['app_secret'],
'name': 'facebook_app_secret',
'description': 'Your Facebook app secret.',
'input_type': 'text'
},
{'label': 'Request Authorization',
'value': 'Request Authorization',
'name': 'facebook_facebook_auth',
'description': 'Request Facebook authorization. (Ensure you allow the browser pop-up).',
'input_type': 'button'
},
{'label': 'Facebook Access Token',
'value': self.config['access_token'],
'name': 'facebook_access_token',
'description': 'Your Facebook access token. '
'Automatically filled in after requesting authorization.',
'input_type': 'text'
},
{'label': 'Facebook Group ID',
'value': self.config['group_id'],
'name': 'facebook_group_id',
'description': 'Your Facebook Group ID.',
'input_type': 'text'
},
{'label': 'Include Subject Line',
'value': self.config['incl_subject'],
'name': 'facebook_incl_subject',
'description': 'Include the subject line with the notifications.',
'input_type': 'checkbox'
},
{'label': 'Include Rich Metadata Info',
'value': self.config['incl_card'],
'name': 'facebook_incl_card',
'description': 'Include an info card with a poster and metadata with the notifications.<br>'
'Note: <a data-tab-destination="3rd_party_apis" data-dismiss="modal" '
'data-target="notify_upload_posters">Image Hosting</a> '
'must be enabled under the notifications settings tab.',
'input_type': 'checkbox'
},
{'label': 'Movie Link Source',
'value': self.config['movie_provider'],
'name': 'facebook_movie_provider',
'description': 'Select the source for movie links on the info cards. Leave blank to disable.<br>'
'Note: 3rd party API lookup may need to be enabled under the notifications settings tab.',
'input_type': 'select',
'select_options': PrettyMetadata().get_movie_providers()
},
{'label': 'TV Show Link Source',
'value': self.config['tv_provider'],
'name': 'facebook_tv_provider',
'description': 'Select the source for tv show links on the info cards. Leave blank to disable.<br>'
'Note: 3rd party API lookup may need to be enabled under the notifications settings tab.',
'input_type': 'select',
'select_options': PrettyMetadata().get_tv_providers()
},
{'label': 'Music Link Source',
'value': self.config['music_provider'],
'name': 'facebook_music_provider',
'description': 'Select the source for music links on the info cards. Leave blank to disable.',
'input_type': 'select',
'select_options': PrettyMetadata().get_music_providers()
}
]
return config_option
class GROUPME(Notifier):
"""
GroupMe notifications
@@ -1715,7 +1518,7 @@ class GROUPME(Notifier):
pretty_metadata = PrettyMetadata(kwargs.get('parameters'))
# Retrieve the poster from Plex
result = pmsconnect.PmsConnect().get_image(img=pretty_metadata.parameters.get('poster_thumb',''))
result = pmsconnect.PmsConnect().get_image(img=pretty_metadata.parameters.get('poster_thumb', ''))
if result and result[0]:
poster_content = result[0]
else:
@@ -1811,12 +1614,13 @@ class GROWL(Notifier):
logger.error("Tautulli Notifiers :: {name} notification failed: network error".format(name=self.NAME))
return False
except gntp.notifier.errors.AuthError:
logger.error("Tautulli Notifiers :: {name} notification failed: authentication error".format(name=self.NAME))
logger.error(
"Tautulli Notifiers :: {name} notification failed: authentication error".format(name=self.NAME))
return False
# Send it, including an image
image_file = os.path.join(str(jellypy.PROG_DIR),
"data/interfaces/default/images/logo-circle.png")
"data/interfaces/default/images/logo-circle.png")
with open(image_file, 'rb') as f:
image = f.read()
@@ -1882,7 +1686,8 @@ class IFTTT(Notifier):
'value': self.config['key'],
'name': 'ifttt_key',
'description': 'Your IFTTT webhook key. You can get a key from'
' <a href="' + helpers.anon_url('https://ifttt.com/maker_webhooks') + '" target="_blank">here</a>.',
' <a href="' + helpers.anon_url(
'https://ifttt.com/maker_webhooks') + '" target="_blank">here</a>.',
'input_type': 'text'
},
{'label': 'IFTTT Event',
@@ -1961,10 +1766,13 @@ class JOIN(Notifier):
return True
else:
error_msg = response_data.get('errorMessage')
logger.error("Tautulli Notifiers :: {name} notification failed: {msg}".format(name=self.NAME, msg=error_msg))
logger.error(
"Tautulli Notifiers :: {name} notification failed: {msg}".format(name=self.NAME, msg=error_msg))
return False
else:
logger.error("Tautulli Notifiers :: {name} notification failed: [{r.status_code}] {r.reason}".format(name=self.NAME, r=r))
logger.error(
"Tautulli Notifiers :: {name} notification failed: [{r.status_code}] {r.reason}".format(name=self.NAME,
r=r))
logger.debug("Tautulli Notifiers :: Request response: {}".format(request.server_message(r, True)))
return False
@@ -1985,14 +1793,19 @@ class JOIN(Notifier):
devices.update({d['deviceName']: d['deviceName'] for d in response_devices})
else:
error_msg = response_data.get('errorMessage')
logger.error("Tautulli Notifiers :: Unable to retrieve {name} devices list: {msg}".format(name=self.NAME, msg=error_msg))
logger.error(
"Tautulli Notifiers :: Unable to retrieve {name} devices list: {msg}".format(name=self.NAME,
msg=error_msg))
else:
logger.error("Tautulli Notifiers :: Unable to retrieve {name} devices list: [{r.status_code}] {r.reason}".format(name=self.NAME, r=r))
logger.error(
"Tautulli Notifiers :: Unable to retrieve {name} devices list: [{r.status_code}] {r.reason}".format(
name=self.NAME, r=r))
logger.debug("Tautulli Notifiers :: Request response: {}".format(request.server_message(r, True)))
except Exception as e:
logger.error("Tautulli Notifiers :: Unable to retrieve {name} devices list: {msg}".format(name=self.NAME, msg=e))
logger.error(
"Tautulli Notifiers :: Unable to retrieve {name} devices list: {msg}".format(name=self.NAME, msg=e))
return devices
@@ -2092,7 +1905,8 @@ class MQTT(Notifier):
if self.config['password']:
auth['password'] = self.config['password']
single(self.config['topic'], payload=json.dumps(data), qos=self.config['qos'], retain=bool(self.config['retain']),
single(self.config['topic'], payload=json.dumps(data), qos=self.config['qos'],
retain=bool(self.config['retain']),
hostname=self.config['broker'], port=self.config['port'], client_id=self.config['clientid'],
keepalive=self.config['keep_alive'], auth=auth or None, protocol=self.config['protocol'])
@@ -2202,6 +2016,7 @@ class OSX(Notifier):
def wrapper(self, *args, **kwargs):
return func(self, old_IMP, *args, **kwargs)
new_IMP = self.objc.selector(wrapper, selector=old_IMP.selector,
signature=old_IMP.signature)
self.objc.classAddMethod(cls, SEL, new_IMP)
@@ -2217,8 +2032,8 @@ class OSX(Notifier):
try:
self._swizzle(self.objc.lookUpClass('NSBundle'),
b'bundleIdentifier',
self._swizzled_bundleIdentifier)
b'bundleIdentifier',
self._swizzled_bundleIdentifier)
NSUserNotification = self.objc.lookUpClass('NSUserNotification')
NSUserNotificationCenter = self.objc.lookUpClass('NSUserNotificationCenter')
@@ -2323,9 +2138,11 @@ class PLEX(Notifier):
image = os.path.join(jellypy.DATA_DIR, os.path.abspath("data/interfaces/default/images/logo-circle.png"))
for host in hosts:
logger.info("Tautulli Notifiers :: Sending notification command to {name} @ {host}".format(name=self.NAME, host=host))
logger.info("Tautulli Notifiers :: Sending notification command to {name} @ {host}".format(name=self.NAME,
host=host))
try:
version = self._sendjson(host, 'Application.GetProperties', {'properties': ['version']})['version']['major']
version = self._sendjson(host, 'Application.GetProperties', {'properties': ['version']})['version'][
'major']
if version < 12: # Eden
notification = subject + "," + body + "," + str(display_time)
@@ -2410,7 +2227,7 @@ class PLEXMOBILEAPP(Notifier):
if action == 'test':
tests = []
for configuration in self.configurations:
tests.append(self.agent_notify(subject=subject, body=body, action='test_'+configuration))
tests.append(self.agent_notify(subject=subject, body=body, action='test_' + configuration))
return all(tests)
configuration_action = action.split('test_')[-1]
@@ -2689,7 +2506,8 @@ class PUSHBULLET(Notifier):
logger.debug("Tautulli Notifiers :: Request response: {}".format(request.server_message(r, True)))
except Exception as e:
logger.error("Tautulli Notifiers :: Unable to retrieve {name} devices list: {msg}".format(name=self.NAME, msg=e))
logger.error(
"Tautulli Notifiers :: Unable to retrieve {name} devices list: {msg}".format(name=self.NAME, msg=e))
return devices
@@ -3016,7 +2834,7 @@ class SCRIPTS(Notifier):
'TAUTULLI_APIKEY': jellypy.CONFIG.API_KEY,
'TAUTULLI_ENCODING': jellypy.SYS_ENCODING,
'TAUTULLI_PYTHON_VERSION': common.PYTHON_VERSION
}
}
if user_id:
user_tokens = users.Users().get_tokens(user_id=user_id)
@@ -3144,7 +2962,7 @@ class SCRIPTS(Notifier):
def _return_config_options(self):
config_option = [{'label': 'Supported File Types',
'description': '<span class="inline-pre">' + \
', '.join(self.script_exts) + '</span>',
', '.join(self.script_exts) + '</span>',
'input_type': 'help'
},
{'label': 'Script Folder',
@@ -3518,7 +3336,7 @@ class TWITTER(Notifier):
poster_url = ''
if self.config['incl_poster'] and kwargs.get('parameters'):
parameters = kwargs['parameters']
poster_url = parameters.get('poster_url','')
poster_url = parameters.get('poster_url', '')
# Hack to add media type to attachment
if poster_url and not helpers.get_img_service():
@@ -3688,7 +3506,8 @@ class XBMC(Notifier):
for host in hosts:
logger.info("Tautulli Notifiers :: Sending notification command to XMBC @ " + host)
try:
version = self._sendjson(host, 'Application.GetProperties', {'properties': ['version']})['version']['major']
version = self._sendjson(host, 'Application.GetProperties', {'properties': ['version']})['version'][
'major']
if version < 12: # Eden
notification = subject + "," + body + "," + str(display_time)