Import Plexivity database

This commit is contained in:
JonnyWong16 2016-05-12 23:50:04 -07:00
parent 6aa786698e
commit 4311d12603
8 changed files with 536 additions and 55 deletions

5
API.md
View file

@ -1429,11 +1429,12 @@ Returns:
``` ```
### import_plexwatch_database ### import_database
Import a plexwatch database into PlexPy. Import a PlexWatch or Plexivity database into PlexPy.
``` ```
Required parameters: Required parameters:
app (str): "plexwatch" or "plexivity"
database_path (str): The full path to the plexwatch database file database_path (str): The full path to the plexwatch database file
table_name (str): "processed" or "grouped" table_name (str): "processed" or "grouped"

View file

@ -2,11 +2,18 @@
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button> <button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button>
<h4 class="modal-title">Import PlexWatch Database</h4> <h4 class="modal-title">Import ${app} Database</h4>
</div> </div>
<div class="modal-body" id="modal-text"> <div class="modal-body" id="modal-text">
<p class="help-block"> <p class="help-block">
Please ensure your PlexWatch database is at version 0.3.2 or higher. <%
v = ''
if app == 'PlexWatch':
v = '0.3.2'
elif app == 'Plexivity':
v = '0.9.8'
%>
<strong>Please ensure your ${app} database is at version ${v} or higher.</strong>
</p> </p>
<div class="form-group"> <div class="form-group">
<label for="db_location">Database Location</label> <label for="db_location">Database Location</label>
@ -15,7 +22,7 @@
<input type="text" class="form-control" id="db_location" name="db_location" value="" required> <input type="text" class="form-control" id="db_location" name="db_location" value="" required>
</div> </div>
</div> </div>
<p class="help-block">Enter the path and file name for the PlexWatch database you wish to import.</p> <p class="help-block">Enter the path and file name for the ${app} database you wish to import.</p>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="table_name">Table Name</label> <label for="table_name">Table Name</label>
@ -41,7 +48,7 @@
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<div> <div>
<span id="status-message"></span> <span id="status-message" style="padding-right: 25px;"></span>
<input type="button" id="import_db" class="btn btn-bright" value="Import"> <input type="button" id="import_db" class="btn btn-bright" value="Import">
</div> </div>
</div> </div>
@ -54,8 +61,13 @@
var table_name = $("#table_name").val(); var table_name = $("#table_name").val();
var import_ignore_interval = $("#import_ignore_interval").val(); var import_ignore_interval = $("#import_ignore_interval").val();
$.ajax({ $.ajax({
url: 'get_plexwatch_export_data', url: 'import_database',
data: {database_path: database_path, table_name:table_name, import_ignore_interval:import_ignore_interval}, data: {
app: "${app}",
database_path: database_path,
table_name: table_name,
import_ignore_interval: import_ignore_interval
},
cache: false, cache: false,
async: true, async: true,
success: function(data) { success: function(data) {

View file

@ -755,9 +755,13 @@
</div> </div>
<div class="padded-header"> <div class="padded-header">
<h3>PlexWatch Import Tool</h3> <h3>Database Import Tool</h3>
</div>
<p class="help-block">Click a button below to import an exisiting database from another app.</p>
<div class="btn-group">
<button class="btn btn-form toggle-app-import-modal" type="button" data-target="#app-import-modal" data-toggle="modal" data-app="plexwatch">PlexWatch</button>
<button class="btn btn-form toggle-app-import-modal" type="button" data-target="#app-import-modal" data-toggle="modal" data-app="plexivity">Plexivity</button>
</div> </div>
<p class="help-block"><a href="javascript:void(0)" id="toggle-plexwatch-import-modal" data-target="#plexwatch-import-modal" data-toggle="modal">Click here to Import an existing Plexwatch database.</a></p>
<p><input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully"></p> <p><input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully"></p>
</div> </div>
@ -1532,7 +1536,7 @@
</div> </div>
</div> </div>
</div> </div>
<div id="plexwatch-import-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="plexwatch-import-modal"></div> <div id="app-import-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="app-import-modal"></div>
<div id="notification-config-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="notification-config-modal"></div> <div id="notification-config-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="notification-config-modal"></div>
<div id="notification-triggers-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="notification-triggers-modal"></div> <div id="notification-triggers-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="notification-triggers-modal"></div>
<div id="notify-text-sub-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="notify-text-sub-modal"> <div id="notify-text-sub-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="notify-text-sub-modal">
@ -2305,14 +2309,15 @@ $(document).ready(function() {
} }
}); });
// Load PlexWatch import modal // Load database import modal
$("#toggle-plexwatch-import-modal").click(function() { $(".toggle-app-import-modal").click(function() {
$.ajax({ $.ajax({
url: 'plexwatch_import', url: 'import_database_tool',
data: { app: $(this).data('app') },
cache: false, cache: false,
async: true, async: true,
complete: function(xhr, status) { complete: function(xhr, status) {
$("#plexwatch-import-modal").html(xhr.responseText); $("#app-import-modal").html(xhr.responseText);
} }
}); });
}); });

View file

@ -141,11 +141,11 @@
</div> </div>
<div class="wizard-card" data-cardname="card6"> <div class="wizard-card" data-cardname="card6">
<h3>PlexWatch Import</h3> <h3>PlexWatch/Plexivity Import</h3>
<p class="help-block">If you have an existing PlexWatch database, you can import the data into PlexPy.</p> <p class="help-block">If you have an existing PlexWatch/Plexivity database, you can import the data into PlexPy.</p>
<p class="help-block"> <p class="help-block">
When you complete this wizard navigate to the settings menu and to the Extra Settings tab. You will find an import tool there When you complete this wizard navigate to the settings menu and to the Extra Settings tab. You will find an import tool there
which will convert your plexWatch database into a format that PlexPy can read. which will convert your PlexWatch/Plexivity database into a format that PlexPy can read.
</p> </p>
<!-- Figure out best way to get friends list refreshed before adding this back <!-- Figure out best way to get friends list refreshed before adding this back
You can skip this and do it later if you wish.</p> You can skip this and do it later if you wish.</p>
@ -468,25 +468,25 @@
}); });
// Send database path to import script // Send database path to import script
$("#plexwatch-import").click(function() { //$("#plexwatch-import").click(function() {
var database_path = $("#db_location").val(); // var database_path = $("#db_location").val();
var table_name = 'processed'; // var table_name = 'processed';
var import_ignore_interval = 0; // var import_ignore_interval = 0;
$.ajax({ // $.ajax({
url: 'get_plexwatch_export_data', // url: 'get_plexwatch_export_data',
data: {database_path: database_path, table_name:table_name, import_ignore_interval:import_ignore_interval}, // data: {database_path: database_path, table_name:table_name, import_ignore_interval:import_ignore_interval},
cache: false, // cache: false,
async: true, // async: true,
success: function(data) { // success: function(data) {
if (data === 'Import has started. Check the PlexPy logs to monitor any problems.') { // if (data === 'Import has started. Check the PlexPy logs to monitor any problems.') {
$("#plexwatch-import-status").html('Started'); // $("#plexwatch-import-status").html('Started');
} else { // } else {
$("#plexwatch-import-status").html(data); // $("#plexwatch-import-status").html(data);
} // }
$("#db_location").val('') // $("#db_location").val('')
} // }
}); // });
}); //});
function getServerOptions(token) { function getServerOptions(token) {
/* Set token and returns server options */ /* Set token and returns server options */

436
plexpy/plexivity_import.py Normal file
View file

@ -0,0 +1,436 @@
# This file is part of PlexPy.
#
# PlexPy is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PlexPy is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
import arrow
import sqlite3
from xml.dom import minidom
import plexpy
import activity_pinger
import activity_processor
import database
import helpers
import logger
import plextv
import users
def extract_plexivity_xml(xml=None):
output = {}
clean_xml = helpers.latinToAscii(xml)
try:
xml_parse = minidom.parseString(clean_xml)
except:
logger.warn(u"PlexPy Importer :: Error parsing XML for Plexivity database.")
return None
# I think Plexivity only tracked videos and not music?
xml_head = xml_parse.getElementsByTagName('Video')
if not xml_head:
logger.warn(u"PlexPy Importer :: Error parsing XML for Plexivity database.")
return None
for a in xml_head:
rating_key = helpers.get_xml_attr(a, 'ratingKey')
added_at = helpers.get_xml_attr(a, 'addedAt')
art = helpers.get_xml_attr(a, 'art')
duration = helpers.get_xml_attr(a, 'duration')
grandparent_rating_key = helpers.get_xml_attr(a, 'grandparentRatingKey')
grandparent_thumb = helpers.get_xml_attr(a, 'grandparentThumb')
grandparent_title = helpers.get_xml_attr(a, 'grandparentTitle')
guid = helpers.get_xml_attr(a, 'guid')
section_id = helpers.get_xml_attr(a, 'librarySectionID')
media_index = helpers.get_xml_attr(a, 'index')
originally_available_at = helpers.get_xml_attr(a, 'originallyAvailableAt')
last_viewed_at = helpers.get_xml_attr(a, 'lastViewedAt')
parent_rating_key = helpers.get_xml_attr(a, 'parentRatingKey')
parent_media_index = helpers.get_xml_attr(a, 'parentIndex')
parent_thumb = helpers.get_xml_attr(a, 'parentThumb')
parent_title = helpers.get_xml_attr(a, 'parentTitle')
rating = helpers.get_xml_attr(a, 'rating')
thumb = helpers.get_xml_attr(a, 'thumb')
media_type = helpers.get_xml_attr(a, 'type')
updated_at = helpers.get_xml_attr(a, 'updatedAt')
view_offset = helpers.get_xml_attr(a, 'viewOffset')
year = helpers.get_xml_attr(a, 'year')
studio = helpers.get_xml_attr(a, 'studio')
title = helpers.get_xml_attr(a, 'title')
tagline = helpers.get_xml_attr(a, 'tagline')
directors = []
if a.getElementsByTagName('Director'):
director_elem = a.getElementsByTagName('Director')
for b in director_elem:
directors.append(helpers.get_xml_attr(b, 'tag'))
aspect_ratio = ''
audio_channels = None
audio_codec = ''
bitrate = None
container = ''
height = None
video_codec = ''
video_framerate = ''
video_resolution = ''
width = None
if a.getElementsByTagName('Media'):
media_elem = a.getElementsByTagName('Media')
for c in media_elem:
aspect_ratio = helpers.get_xml_attr(c, 'aspectRatio')
audio_channels = helpers.get_xml_attr(c, 'audioChannels')
audio_codec = helpers.get_xml_attr(c, 'audioCodec')
bitrate = helpers.get_xml_attr(c, 'bitrate')
container = helpers.get_xml_attr(c, 'container')
height = helpers.get_xml_attr(c, 'height')
video_codec = helpers.get_xml_attr(c, 'videoCodec')
video_framerate = helpers.get_xml_attr(c, 'videoFrameRate')
video_resolution = helpers.get_xml_attr(c, 'videoResolution')
width = helpers.get_xml_attr(c, 'width')
machine_id = ''
platform = ''
player = ''
if a.getElementsByTagName('Player'):
player_elem = a.getElementsByTagName('Player')
for d in player_elem:
ip_address = helpers.get_xml_attr(d, 'address')
machine_id = helpers.get_xml_attr(d, 'machineIdentifier')
platform = helpers.get_xml_attr(d, 'platform')
player = helpers.get_xml_attr(d, 'title')
transcode_audio_channels = None
transcode_audio_codec = ''
audio_decision = 'direct play'
transcode_container = ''
transcode_height = None
transcode_protocol = ''
transcode_video_codec = ''
video_decision = 'direct play'
transcode_width = None
if a.getElementsByTagName('TranscodeSession'):
transcode_elem = a.getElementsByTagName('TranscodeSession')
for e in transcode_elem:
transcode_audio_channels = helpers.get_xml_attr(e, 'audioChannels')
transcode_audio_codec = helpers.get_xml_attr(e, 'audioCodec')
audio_decision = helpers.get_xml_attr(e, 'audioDecision')
transcode_container = helpers.get_xml_attr(e, 'container')
transcode_height = helpers.get_xml_attr(e, 'height')
transcode_protocol = helpers.get_xml_attr(e, 'protocol')
transcode_video_codec = helpers.get_xml_attr(e, 'videoCodec')
video_decision = helpers.get_xml_attr(e, 'videoDecision')
transcode_width = helpers.get_xml_attr(e, 'width')
user_id = None
if a.getElementsByTagName('User'):
user_elem = a.getElementsByTagName('User')
for f in user_elem:
user_id = helpers.get_xml_attr(f, 'id')
writers = []
if a.getElementsByTagName('Writer'):
writer_elem = a.getElementsByTagName('Writer')
for g in writer_elem:
writers.append(helpers.get_xml_attr(g, 'tag'))
actors = []
if a.getElementsByTagName('Role'):
actor_elem = a.getElementsByTagName('Role')
for h in actor_elem:
actors.append(helpers.get_xml_attr(h, 'tag'))
genres = []
if a.getElementsByTagName('Genre'):
genre_elem = a.getElementsByTagName('Genre')
for i in genre_elem:
genres.append(helpers.get_xml_attr(i, 'tag'))
labels = []
if a.getElementsByTagName('Lables'):
label_elem = a.getElementsByTagName('Lables')
for i in label_elem:
labels.append(helpers.get_xml_attr(i, 'tag'))
output = {'rating_key': rating_key,
'added_at': added_at,
'art': art,
'duration': duration,
'grandparent_rating_key': grandparent_rating_key,
'grandparent_thumb': grandparent_thumb,
'grandparent_title': grandparent_title,
'parent_title': parent_title,
'title': title,
'tagline': tagline,
'guid': guid,
'section_id': section_id,
'media_index': media_index,
'originally_available_at': originally_available_at,
'last_viewed_at': last_viewed_at,
'parent_rating_key': parent_rating_key,
'parent_media_index': parent_media_index,
'parent_thumb': parent_thumb,
'rating': rating,
'thumb': thumb,
'media_type': media_type,
'updated_at': updated_at,
'view_offset': view_offset,
'year': year,
'directors': directors,
'aspect_ratio': aspect_ratio,
'audio_channels': audio_channels,
'audio_codec': audio_codec,
'bitrate': bitrate,
'container': container,
'height': height,
'video_codec': video_codec,
'video_framerate': video_framerate,
'video_resolution': video_resolution,
'width': width,
'ip_address': ip_address,
'machine_id': machine_id,
'platform': platform,
'player': player,
'transcode_audio_channels': transcode_audio_channels,
'transcode_audio_codec': transcode_audio_codec,
'audio_decision': audio_decision,
'transcode_container': transcode_container,
'transcode_height': transcode_height,
'transcode_protocol': transcode_protocol,
'transcode_video_codec': transcode_video_codec,
'video_decision': video_decision,
'transcode_width': transcode_width,
'user_id': user_id,
'writers': writers,
'actors': actors,
'genres': genres,
'studio': studio,
'labels': labels
}
return output
def validate_database(database=None, table_name=None):
try:
connection = sqlite3.connect(database, timeout=20)
except sqlite3.OperationalError:
logger.error(u"PlexPy Importer :: Invalid database specified.")
return 'Invalid database specified.'
except ValueError:
logger.error(u"PlexPy Importer :: Invalid database specified.")
return 'Invalid database specified.'
except:
logger.error(u"PlexPy Importer :: Uncaught exception.")
return 'Uncaught exception.'
try:
connection.execute('SELECT xml from %s' % table_name)
connection.close()
except sqlite3.OperationalError:
logger.error(u"PlexPy Importer :: Invalid database specified.")
return 'Invalid database specified.'
except:
logger.error(u"PlexPy Importer :: Uncaught exception.")
return 'Uncaught exception.'
return 'success'
def import_from_plexivity(database=None, table_name=None, import_ignore_interval=0):
try:
connection = sqlite3.connect(database, timeout=20)
connection.row_factory = sqlite3.Row
except sqlite3.OperationalError:
logger.error(u"PlexPy Importer :: Invalid filename.")
return None
except ValueError:
logger.error(u"PlexPy Importer :: Invalid filename.")
return None
try:
connection.execute('SELECT xml from %s' % table_name)
except sqlite3.OperationalError:
logger.error(u"PlexPy Importer :: Database specified does not contain the required fields.")
return None
logger.debug(u"PlexPy Importer :: Plexivity data import in progress...")
logger.debug(u"PlexPy Importer :: Disabling monitoring while import in progress.")
plexpy.schedule_job(activity_pinger.check_active_sessions, 'Check for active sessions',
hours=0, minutes=0, seconds=0)
plexpy.schedule_job(activity_pinger.check_recently_added, 'Check for recently added items',
hours=0, minutes=0, seconds=0)
plexpy.schedule_job(activity_pinger.check_server_response, 'Check for Plex remote access',
hours=0, minutes=0, seconds=0)
ap = activity_processor.ActivityProcessor()
user_data = users.Users()
# Get the latest friends list so we can pull user id's
try:
plextv.refresh_users()
except:
logger.debug(u"PlexPy Importer :: Unable to refresh the users list. Aborting import.")
return None
query = 'SELECT id AS id, ' \
'time AS started, ' \
'stopped, ' \
'null AS user_id, ' \
'user, ' \
'ip_address, ' \
'paused_counter, ' \
'platform AS player, ' \
'null AS platform, ' \
'null as machine_id, ' \
'null AS media_type, ' \
'null AS view_offset, ' \
'xml, ' \
'rating as content_rating,' \
'summary,' \
'title AS full_title,' \
'(case when orig_title_ep = "n/a" then orig_title else ' \
'orig_title_ep end) as title,' \
'(case when orig_title_ep != "n/a" then orig_title else ' \
'null end) as grandparent_title ' \
'FROM ' + table_name + ' ORDER BY id'
result = connection.execute(query)
for row in result:
# Extract the xml from the Plexivity db xml field.
extracted_xml = extract_plexivity_xml(row['xml'])
# If we get back None from our xml extractor skip over the record and log error.
if not extracted_xml:
logger.error(u"PlexPy Importer :: Skipping record with id %s due to malformed xml."
% str(row['id']))
continue
# Skip line if we don't have a ratingKey to work with
#if not row['rating_key']:
# logger.error(u"PlexPy Importer :: Skipping record due to null ratingKey.")
# continue
# If the user_id no longer exists in the friends list, pull it from the xml.
if user_data.get_user_id(user=row['user']):
user_id = user_data.get_user_id(user=row['user'])
else:
user_id = extracted_xml['user_id']
session_history = {'started': arrow.get(row['started']).timestamp,
'stopped': arrow.get(row['stopped']).timestamp,
'rating_key': extracted_xml['rating_key'],
'title': row['title'],
'parent_title': extracted_xml['parent_title'],
'grandparent_title': row['grandparent_title'],
'user_id': user_id,
'user': row['user'],
'ip_address': row['ip_address'] if row['ip_address'] else extracted_xml['ip_address'],
'paused_counter': row['paused_counter'],
'player': row['player'],
'platform': extracted_xml['platform'],
'machine_id': extracted_xml['machine_id'],
'parent_rating_key': extracted_xml['parent_rating_key'],
'grandparent_rating_key': extracted_xml['grandparent_rating_key'],
'media_type': extracted_xml['media_type'],
'view_offset': extracted_xml['view_offset'],
'video_decision': extracted_xml['video_decision'],
'audio_decision': extracted_xml['audio_decision'],
'duration': extracted_xml['duration'],
'width': extracted_xml['width'],
'height': extracted_xml['height'],
'container': extracted_xml['container'],
'video_codec': extracted_xml['video_codec'],
'audio_codec': extracted_xml['audio_codec'],
'bitrate': extracted_xml['bitrate'],
'video_resolution': extracted_xml['video_resolution'],
'video_framerate': extracted_xml['video_framerate'],
'aspect_ratio': extracted_xml['aspect_ratio'],
'audio_channels': extracted_xml['audio_channels'],
'transcode_protocol': extracted_xml['transcode_protocol'],
'transcode_container': extracted_xml['transcode_container'],
'transcode_video_codec': extracted_xml['transcode_video_codec'],
'transcode_audio_codec': extracted_xml['transcode_audio_codec'],
'transcode_audio_channels': extracted_xml['transcode_audio_channels'],
'transcode_width': extracted_xml['transcode_width'],
'transcode_height': extracted_xml['transcode_height']
}
session_history_metadata = {'rating_key': extracted_xml['rating_key'],
'parent_rating_key': extracted_xml['parent_rating_key'],
'grandparent_rating_key': extracted_xml['grandparent_rating_key'],
'title': row['title'],
'parent_title': extracted_xml['parent_title'],
'grandparent_title': row['grandparent_title'],
'media_index': extracted_xml['media_index'],
'parent_media_index': extracted_xml['parent_media_index'],
'thumb': extracted_xml['thumb'],
'parent_thumb': extracted_xml['parent_thumb'],
'grandparent_thumb': extracted_xml['grandparent_thumb'],
'art': extracted_xml['art'],
'media_type': extracted_xml['media_type'],
'year': extracted_xml['year'],
'originally_available_at': extracted_xml['originally_available_at'],
'added_at': extracted_xml['added_at'],
'updated_at': extracted_xml['updated_at'],
'last_viewed_at': extracted_xml['last_viewed_at'],
'content_rating': row['content_rating'],
'summary': row['summary'],
'tagline': extracted_xml['tagline'],
'rating': extracted_xml['rating'],
'duration': extracted_xml['duration'],
'guid': extracted_xml['guid'],
'section_id': extracted_xml['section_id'],
'directors': extracted_xml['directors'],
'writers': extracted_xml['writers'],
'actors': extracted_xml['actors'],
'genres': extracted_xml['genres'],
'studio': extracted_xml['studio'],
'labels': extracted_xml['labels'],
'full_title': row['full_title']
}
# On older versions of PMS, "clip" items were still classified as "movie" and had bad ratingKey values
# Just make sure that the ratingKey is indeed an integer
if session_history_metadata['rating_key'].isdigit():
ap.write_session_history(session=session_history,
import_metadata=session_history_metadata,
is_import=True,
import_ignore_interval=import_ignore_interval)
else:
logger.debug(u"PlexPy Importer :: Item has bad rating_key: %s" % session_history_metadata['rating_key'])
logger.debug(u"PlexPy Importer :: Plexivity data import complete.")
import_users()
logger.debug(u"PlexPy Importer :: Re-enabling monitoring.")
plexpy.initialize_scheduler()
def import_users():
logger.debug(u"PlexPy Importer :: Importing Plexivity Users...")
monitor_db = database.MonitorDatabase()
query = 'INSERT OR IGNORE INTO users (user_id, username) ' \
'SELECT user_id, user ' \
'FROM session_history WHERE user_id != 1 GROUP BY user_id'
try:
monitor_db.action(query)
logger.debug(u"PlexPy Importer :: Users imported.")
except:
logger.debug(u"PlexPy Importer :: Failed to import users.")

View file

@ -32,12 +32,12 @@ def extract_plexwatch_xml(xml=None):
try: try:
xml_parse = minidom.parseString(clean_xml) xml_parse = minidom.parseString(clean_xml)
except: except:
logger.warn(u"PlexPy Importer :: Error parsing XML for Plexwatch database.") logger.warn(u"PlexPy Importer :: Error parsing XML for PlexWatch database.")
return None return None
xml_head = xml_parse.getElementsByTagName('opt') xml_head = xml_parse.getElementsByTagName('opt')
if not xml_head: if not xml_head:
logger.warn(u"PlexPy Importer :: Error parsing XML for Plexwatch database.") logger.warn(u"PlexPy Importer :: Error parsing XML for PlexWatch database.")
return None return None
for a in xml_head: for a in xml_head:
@ -102,6 +102,7 @@ def extract_plexwatch_xml(xml=None):
if a.getElementsByTagName('Player'): if a.getElementsByTagName('Player'):
player_elem = a.getElementsByTagName('Player') player_elem = a.getElementsByTagName('Player')
for d in player_elem: for d in player_elem:
ip_address = helpers.get_xml_attr(d, 'address')
machine_id = helpers.get_xml_attr(d, 'machineIdentifier') machine_id = helpers.get_xml_attr(d, 'machineIdentifier')
platform = helpers.get_xml_attr(d, 'platform') platform = helpers.get_xml_attr(d, 'platform')
player = helpers.get_xml_attr(d, 'title') player = helpers.get_xml_attr(d, 'title')
@ -192,6 +193,7 @@ def extract_plexwatch_xml(xml=None):
'video_framerate': video_framerate, 'video_framerate': video_framerate,
'video_resolution': video_resolution, 'video_resolution': video_resolution,
'width': width, 'width': width,
'ip_address': ip_address,
'machine_id': machine_id, 'machine_id': machine_id,
'platform': platform, 'platform': platform,
'player': player, 'player': player,
@ -332,7 +334,7 @@ def import_from_plexwatch(database=None, table_name=None, import_ignore_interval
'grandparent_title': row['grandparent_title'], 'grandparent_title': row['grandparent_title'],
'user_id': user_id, 'user_id': user_id,
'user': row['user'], 'user': row['user'],
'ip_address': row['ip_address'], 'ip_address': row['ip_address'] if row['ip_address'] else extracted_xml['ip_address'],
'paused_counter': row['paused_counter'], 'paused_counter': row['paused_counter'],
'player': row['player'], 'player': row['player'],
'platform': extracted_xml['platform'], 'platform': extracted_xml['platform'],

View file

@ -585,7 +585,7 @@ class Users(object):
except Exception as e: except Exception as e:
logger.warn(u"PlexPy Users :: Unable to execute database query for undelete: %s." % e) logger.warn(u"PlexPy Users :: Unable to execute database query for undelete: %s." % e)
# Keep method for PlexWatch import # Keep method for PlexWatch/Plexivity import
def get_user_id(self, user=None): def get_user_id(self, user=None):
if user: if user:
try: try:

View file

@ -40,6 +40,7 @@ import log_reader
import logger import logger
import notifiers import notifiers
import plextv import plextv
import plexivity_import
import plexwatch_import import plexwatch_import
import pmsconnect import pmsconnect
import users import users
@ -2630,12 +2631,13 @@ class WebInterface(object):
@cherrypy.expose @cherrypy.expose
@requireAuth(member_of("admin")) @requireAuth(member_of("admin"))
@addtoapi("import_plexwatch_database") @addtoapi()
def get_plexwatch_export_data(self, database_path=None, table_name=None, import_ignore_interval=0, **kwargs): def import_database(self, app=None, database_path=None, table_name=None, import_ignore_interval=0, **kwargs):
""" Import a plexwatch database into PlexPy. """ Import a PlexWatch or Plexivity database into PlexPy.
``` ```
Required parameters: Required parameters:
app (str): "plexwatch" or "plexivity"
database_path (str): The full path to the plexwatch database file database_path (str): The full path to the plexwatch database file
table_name (str): "processed" or "grouped" table_name (str): "processed" or "grouped"
@ -2646,6 +2648,10 @@ class WebInterface(object):
None None
``` ```
""" """
if not app:
return 'No app specified for import'
if app.lower() == 'plexwatch':
db_check_msg = plexwatch_import.validate_database(database=database_path, db_check_msg = plexwatch_import.validate_database(database=database_path,
table_name=table_name) table_name=table_name)
if db_check_msg == 'success': if db_check_msg == 'success':
@ -2656,11 +2662,30 @@ class WebInterface(object):
return 'Import has started. Check the PlexPy logs to monitor any problems.' return 'Import has started. Check the PlexPy logs to monitor any problems.'
else: else:
return db_check_msg return db_check_msg
elif app.lower() == 'plexivity':
db_check_msg = plexivity_import.validate_database(database=database_path,
table_name=table_name)
if db_check_msg == 'success':
threading.Thread(target=plexivity_import.import_from_plexivity,
kwargs={'database': database_path,
'table_name': table_name,
'import_ignore_interval': import_ignore_interval}).start()
return 'Import has started. Check the PlexPy logs to monitor any problems.'
else:
return db_check_msg
else:
return 'App not recognized for import'
@cherrypy.expose @cherrypy.expose
@requireAuth(member_of("admin")) @requireAuth(member_of("admin"))
def plexwatch_import(self, **kwargs): def import_database_tool(self, app=None, **kwargs):
return serve_template(templatename="plexwatch_import.html", title="Import PlexWatch Database") if app == 'plexwatch':
return serve_template(templatename="app_import.html", title="Import PlexWatch Database", app="PlexWatch")
elif app == 'plexivity':
return serve_template(templatename="app_import.html", title="Import Plexivity Database", app="Plexivity")
logger.warn(u"No app specified for import.")
return
@cherrypy.expose @cherrypy.expose
@requireAuth(member_of("admin")) @requireAuth(member_of("admin"))