Updated modules and DB functions - service needs DB update function added
This commit is contained in:
parent
d141895328
commit
9be5f646da
66
dbtest.py
66
dbtest.py
|
@ -1,66 +0,0 @@
|
||||||
import sys
|
|
||||||
sys.path.insert(0,'lib')
|
|
||||||
import dbutils
|
|
||||||
import libsonic
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
db = None
|
|
||||||
connection = None
|
|
||||||
|
|
||||||
db_filename = "subsonic_sqlite.db"
|
|
||||||
|
|
||||||
def get_db():
|
|
||||||
global db_filename
|
|
||||||
global db
|
|
||||||
print("Getting DB %s"%db_filename)
|
|
||||||
try:
|
|
||||||
db = dbutils.SQLiteDatabase(db_filename)
|
|
||||||
except Exception as e:
|
|
||||||
print("Connecting to DB failed: %s"%e)
|
|
||||||
return db
|
|
||||||
|
|
||||||
def get_connection():
|
|
||||||
global connection
|
|
||||||
|
|
||||||
if connection==None:
|
|
||||||
connected = False
|
|
||||||
# Create connection
|
|
||||||
try:
|
|
||||||
connection = libsonic.Connection(
|
|
||||||
baseUrl="http://192.168.25.16",
|
|
||||||
username="warwick.harris",
|
|
||||||
password="ducatiMonsterSoundsGreat$",
|
|
||||||
port="4040",
|
|
||||||
apiVersion="1.15.1",
|
|
||||||
insecure=False,
|
|
||||||
legacyAuth=False,
|
|
||||||
useGET=False,
|
|
||||||
)
|
|
||||||
connected = connection.ping()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if connected==False:
|
|
||||||
print('Connection error')
|
|
||||||
return False
|
|
||||||
|
|
||||||
return connection
|
|
||||||
|
|
||||||
db = get_db()
|
|
||||||
connection = get_connection()
|
|
||||||
|
|
||||||
#cursor = db.get_cursor()
|
|
||||||
#cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")
|
|
||||||
#print(cursor.fetchall())
|
|
||||||
artist_id = 635
|
|
||||||
artist_info = connection.getArtistInfo2(artist_id)
|
|
||||||
#print("Artist info: %s"%artist_info)
|
|
||||||
print(db.update_artist(artist_id, artist_info, time.time()))
|
|
||||||
print(db.get_artist_info(artist_id))
|
|
||||||
print(db.update_artist(artist_id, "replace", time.time()))
|
|
||||||
print(db.get_artist_info(1))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.close()
|
|
|
@ -1,8 +1,16 @@
|
||||||
import sqlite3 as sql
|
import sqlite3 as sql
|
||||||
|
import time
|
||||||
|
|
||||||
tbl_artist_info_ddl = str('CREATE TABLE artist_info ('
|
tbl_artist_info_ddl = str('CREATE TABLE artist_info ('
|
||||||
'artist_id TEXT NOT NULL PRIMARY KEY,'
|
'artist_id TEXT NOT NULL PRIMARY KEY,'
|
||||||
|
'artist_name TEXT,'
|
||||||
'artist_info TEXT,'
|
'artist_info TEXT,'
|
||||||
|
'mb_artist_id TEXT,'
|
||||||
|
'image_url TEXT,'
|
||||||
|
'wikidata_url TEXT,'
|
||||||
|
'wikipedia_url TEXT,'
|
||||||
|
'wikipedia_image TEXT,'
|
||||||
|
'wikipedia_extract TEXT,'
|
||||||
'last_update TEXT);')
|
'last_update TEXT);')
|
||||||
|
|
||||||
class SQLiteDatabase(object):
|
class SQLiteDatabase(object):
|
||||||
|
@ -46,6 +54,7 @@ class SQLiteDatabase(object):
|
||||||
cursor.execute(query, params)
|
cursor.execute(query, params)
|
||||||
else:
|
else:
|
||||||
cursor.execute(query)
|
cursor.execute(query)
|
||||||
|
print("%s rows affected"%cursor.rowcount)
|
||||||
return cursor
|
return cursor
|
||||||
except sql.Error as e:
|
except sql.Error as e:
|
||||||
print("SQLite error %s"%e.args[0])
|
print("SQLite error %s"%e.args[0])
|
||||||
|
@ -55,10 +64,35 @@ class SQLiteDatabase(object):
|
||||||
print("Error params %s"%str(params))
|
print("Error params %s"%str(params))
|
||||||
print("Error params type %s"%type(params))
|
print("Error params type %s"%type(params))
|
||||||
|
|
||||||
def update_artist(self, artist_id, artist_info, update_time):
|
def get_record_age(self, artist_id):
|
||||||
|
try:
|
||||||
|
last_update = self.get_value(artist_id, 'last_update')
|
||||||
|
record_age = round(time.time())-round(float(last_update[0][0]))
|
||||||
|
return record_age
|
||||||
|
except Exception as e:
|
||||||
|
print("get_record_age failed %s" % e)
|
||||||
|
return
|
||||||
|
|
||||||
|
def get_artist_info(self, artist_id):
|
||||||
|
query = 'SELECT * FROM artist_info WHERE artist_id = ?'# %str(artist_id)
|
||||||
|
params = [str(artist_id)]
|
||||||
|
cursor = self.run_query(query, params)
|
||||||
|
return cursor.fetchall()
|
||||||
|
|
||||||
|
def get_all(self):
|
||||||
|
query = 'SELECT * FROM artist_info'
|
||||||
|
#params = [str(artist_id)]
|
||||||
|
cursor = self.run_query(query)#, params)
|
||||||
|
return cursor.fetchall()
|
||||||
|
|
||||||
|
def update_value(self, artist_id, field_name, field_value):
|
||||||
success = False
|
success = False
|
||||||
query = 'INSERT or REPLACE INTO artist_info VALUES (?, ?, ?)'
|
query = 'UPDATE artist_info SET %s = ?, last_update = ? WHERE artist_id = ?' % str(field_name)
|
||||||
params = (str(artist_id), str(artist_info), str(update_time))
|
params = [str(field_value), str(time.time()), str(artist_id)]
|
||||||
|
cursor = self.run_query(query, params)
|
||||||
|
if (cursor.rowcount == 0):
|
||||||
|
query = 'INSERT OR IGNORE INTO artist_info (artist_id, %s, last_update) VALUES (?, ?, ?)' % str(field_name)
|
||||||
|
params = [str(artist_id), str(field_value), str(time.time())]
|
||||||
cursor = self.run_query(query, params)
|
cursor = self.run_query(query, params)
|
||||||
try:
|
try:
|
||||||
self.conn.commit()
|
self.conn.commit()
|
||||||
|
@ -68,8 +102,8 @@ class SQLiteDatabase(object):
|
||||||
pass
|
pass
|
||||||
return success
|
return success
|
||||||
|
|
||||||
def get_artist_info(self, artist_id):
|
def get_value(self, artist_id, field_name):
|
||||||
query = 'SELECT * FROM artist_info WHERE artist_id = ?'
|
query = 'SELECT %s FROM artist_info WHERE artist_id = ?' % str(field_name)
|
||||||
params = [str(artist_id)]
|
params = [str(artist_id)]
|
||||||
cursor = self.run_query(query, params)
|
cursor = self.run_query(query, params)
|
||||||
return cursor.fetchall()
|
return cursor.fetchall()
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
"""
|
||||||
|
Musicbrainz utilities for plugin.audio.subsonic
|
||||||
|
"""
|
||||||
|
from .mbconnection import *
|
||||||
|
|
||||||
|
__version__ = '0.0.1'
|
|
@ -0,0 +1,146 @@
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import urllib.request
|
||||||
|
from urllib.parse import urlencode
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
import re
|
||||||
|
|
||||||
|
urllib.request.install_opener(urllib.request.build_opener(urllib.request.HTTPSHandler))
|
||||||
|
|
||||||
|
class MBConnection(object):
|
||||||
|
def __init__(self, lang = "en"):
|
||||||
|
self._lang = lang
|
||||||
|
self._baseUrl = "https://musicbrainz.org/ws/2"
|
||||||
|
self._wikipediaBaseUrl = "https://{}.wikipedia.org/wiki".format(self._lang)
|
||||||
|
self._wikidataBaseUrl = "https://www.wikidata.org/wiki/Special:EntityData"
|
||||||
|
self._opener = self._getOpener()
|
||||||
|
|
||||||
|
def _getOpener(self):
|
||||||
|
opener = urllib.request.build_opener(urllib.request.HTTPSHandler)
|
||||||
|
return opener
|
||||||
|
|
||||||
|
def search(self, entity, query, limit=None, offset=None):
|
||||||
|
viewName = '%s' % entity
|
||||||
|
q = self._getQueryDict({'query': query, 'limit': limit, 'offset': offset})
|
||||||
|
req = self._getRequest(self._baseUrl, viewName, q)
|
||||||
|
res = self._doInfoReqXml(req)
|
||||||
|
return res
|
||||||
|
|
||||||
|
def get_wiki_extract(self, title):
|
||||||
|
try:
|
||||||
|
if('http' in title):
|
||||||
|
#accepts search text or full url https://en.wikipedia.org/wiki/Alex_Lloyd
|
||||||
|
pattern = 'wikipedia.org/wiki/(.+)'
|
||||||
|
title = re.search(pattern, title).group(1)
|
||||||
|
viewName = 'api.php'
|
||||||
|
q = self._getQueryDict({'format' : 'json', 'action' : 'query', 'prop' : 'extracts', 'redirects' : 1, 'titles' : title})
|
||||||
|
req = self._getRequest(self._wikipediaBaseUrl[:-3], viewName, q, 'exintro&explaintext&')
|
||||||
|
res = self._doInfoReqJson(req)
|
||||||
|
pages = res['query']['pages']
|
||||||
|
extract = list(pages.values())[0]['extract']
|
||||||
|
return extract
|
||||||
|
except Exception as e:
|
||||||
|
print("get_artist_wikpedia failed %s"%e)
|
||||||
|
return
|
||||||
|
|
||||||
|
#https://en.wikipedia.org/w/api.php?exintro&explaintext&format=json&action=query&prop=extracts&redirects=1&titles=%C3%89milie_Simon
|
||||||
|
def get_wiki_image(self, title):
|
||||||
|
try:
|
||||||
|
if('http' in title):
|
||||||
|
#accepts search text or full url https://en.wikipedia.org/wiki/Alex_Lloyd
|
||||||
|
pattern = 'wikipedia.org/wiki/(.+)'
|
||||||
|
title = re.search(pattern, title).group(1)
|
||||||
|
viewName = 'api.php'
|
||||||
|
q = self._getQueryDict({'format' : 'json', 'action' : 'query', 'prop' : 'pageimages', 'pithumbsize' : 800, 'titles' : title})
|
||||||
|
req = self._getRequest(self._wikipediaBaseUrl[:-3], viewName, q)
|
||||||
|
res = self._doInfoReqJson(req)
|
||||||
|
pages = res['query']['pages']
|
||||||
|
print(res['query']['pages'])
|
||||||
|
image_url = list(pages.values())[0]['thumbnail']['source']
|
||||||
|
return image_url
|
||||||
|
except Exception as e:
|
||||||
|
print("get_wiki_image failed %s"%e)
|
||||||
|
return
|
||||||
|
|
||||||
|
def get_artist_id(self, query):
|
||||||
|
try:
|
||||||
|
dres = self.search('artist', query)
|
||||||
|
artist_list = dres.find('{http://musicbrainz.org/ns/mmd-2.0#}artist-list')
|
||||||
|
artist = artist_list.find('{http://musicbrainz.org/ns/mmd-2.0#}artist')
|
||||||
|
return artist.attrib['id']
|
||||||
|
except Exception as e:
|
||||||
|
print("get_artist_id failed %s"%e)
|
||||||
|
return
|
||||||
|
|
||||||
|
def get_relation(self, artist_id, rel_type):
|
||||||
|
try:
|
||||||
|
viewName = 'artist/%s' % artist_id
|
||||||
|
q = self._getQueryDict({'inc': "url-rels"})
|
||||||
|
req = self._getRequest(self._baseUrl, viewName, q)
|
||||||
|
res = self._doInfoReqXml(req)
|
||||||
|
for relation in res.iter('{http://musicbrainz.org/ns/mmd-2.0#}relation'):
|
||||||
|
if relation.attrib['type'] == rel_type:
|
||||||
|
return relation.find('{http://musicbrainz.org/ns/mmd-2.0#}target').text
|
||||||
|
except Exception as e:
|
||||||
|
print("get_artist_image failed %s"%e)
|
||||||
|
return
|
||||||
|
|
||||||
|
def get_artist_image(self, artist_id):
|
||||||
|
try:
|
||||||
|
image = self.get_relation(artist_id, 'image')
|
||||||
|
return image
|
||||||
|
except Exception as e:
|
||||||
|
print("get_artist_image failed %s"%e)
|
||||||
|
return
|
||||||
|
|
||||||
|
def get_artist_wikpedia(self, artist_id):
|
||||||
|
wikidata_url = self.get_relation(artist_id, 'wikidata')
|
||||||
|
pattern = 'www.wikidata.org/wiki/(Q\d+)'
|
||||||
|
try:
|
||||||
|
wikidata_ref = re.search(pattern, wikidata_url).group(1)
|
||||||
|
viewName = '%s.rdf' % wikidata_ref
|
||||||
|
q = self._getQueryDict({})
|
||||||
|
req = self._getRequest(self._wikidataBaseUrl, viewName, q )
|
||||||
|
res = self._doInfoReqXml(req)
|
||||||
|
for item in res.iter('{http://www.w3.org/1999/02/22-rdf-syntax-ns#}Description'):
|
||||||
|
try:
|
||||||
|
url = item.attrib['{http://www.w3.org/1999/02/22-rdf-syntax-ns#}about']
|
||||||
|
if self._wikipediaBaseUrl in url:
|
||||||
|
#print(urlencode(url))
|
||||||
|
#print((url.encode().decode('unicode-escape')))
|
||||||
|
return urllib.parse.unquote(url)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
except Exception as e:
|
||||||
|
print("get_artist_wikpedia failed %s"%e)
|
||||||
|
return
|
||||||
|
|
||||||
|
def _getQueryDict(self, d):
|
||||||
|
"""
|
||||||
|
Given a dictionary, it cleans out all the values set to None
|
||||||
|
"""
|
||||||
|
for k, v in list(d.items()):
|
||||||
|
if v is None:
|
||||||
|
del d[k]
|
||||||
|
return d
|
||||||
|
|
||||||
|
def _getRequest(self, baseUrl, viewName, query={}, prefix=""):
|
||||||
|
qdict = {}
|
||||||
|
qdict.update(query)
|
||||||
|
url = '%s/%s' % (baseUrl, viewName)
|
||||||
|
if(prefix!='' or qdict!={}):
|
||||||
|
url += "?%s%s" % (prefix, urlencode(qdict))
|
||||||
|
print("UseGET URL %s" % (url))
|
||||||
|
req = urllib.request.Request(url)
|
||||||
|
return req
|
||||||
|
|
||||||
|
def _doInfoReqXml(self, req):
|
||||||
|
res = urllib.request.urlopen(req)
|
||||||
|
data = res.read().decode('utf-8')
|
||||||
|
dres = ET.fromstring(data)
|
||||||
|
return dres
|
||||||
|
|
||||||
|
def _doInfoReqJson(self, req):
|
||||||
|
res = urllib.request.urlopen(req)
|
||||||
|
dres = json.loads(res.read().decode('utf-8'))
|
||||||
|
return dres
|
51
main.py
51
main.py
|
@ -756,25 +756,22 @@ def get_entry_playlist(item,params):
|
||||||
|
|
||||||
def get_artist_info(artist_id, forced=False):
|
def get_artist_info(artist_id, forced=False):
|
||||||
db = get_db()
|
db = get_db()
|
||||||
artist_info = {}
|
artist_info = ""
|
||||||
print("Retreiving artist info for id: %s"%(artist_id))
|
print("Retreiving artist info for id: %s"%(artist_id))
|
||||||
popup("Updating artist info\nplease wait")
|
#popup("Updating artist info\nplease wait")
|
||||||
try:
|
try:
|
||||||
artist_record = db.get_artist_info(artist_id)
|
artist_info = db.get_value(artist_id, 'artist_info')[0][0]
|
||||||
print("Outer %s"%len(artist_record))
|
artist_wiki = db.get_value(artist_id, 'wikipedia_extract')[0][0]
|
||||||
if(len(artist_record)==0):
|
#plugin.log("Artist info: %s"%artist_info)
|
||||||
print("Empty record, getting data for %s"%artist_id)
|
#plugin.log("Artist wiki: %s"%artist_wiki)
|
||||||
artist_info = json.dumps(connection.getArtistInfo2(artist_id).get('artistInfo2'))
|
#plugin.log("Len Artist info: %s"%len(artist_info))
|
||||||
print("Adding to DB artist info: %s"%artist_info)
|
#plugin.log("Len Artist wiki: %s"%len(artist_wiki))
|
||||||
if(db.update_artist(artist_id, artist_info, time.time())):
|
if(len(artist_info)<10):
|
||||||
plugin.log("Success")
|
print("Using wiki data")
|
||||||
else:
|
artist_info = artist_wiki
|
||||||
plugin.log("Failed")
|
if(artist_info is None):
|
||||||
artist_record = db.get_artist_info(artist_id)
|
print("artist_info is None making empty string")
|
||||||
artist_info = json.loads(artist_record[0][1])
|
artist_info = ""
|
||||||
last_update = artist_record[0][2]
|
|
||||||
plugin.log("Artist info: %s"%artist_info)
|
|
||||||
plugin.log("Last update: %s"%last_update)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("Error get info from DB %s"%e)
|
print("Error get info from DB %s"%e)
|
||||||
return artist_info
|
return artist_info
|
||||||
|
@ -782,8 +779,12 @@ def get_artist_info(artist_id, forced=False):
|
||||||
def get_entry_artist(item,params):
|
def get_entry_artist(item,params):
|
||||||
image = connection.getCoverArtUrl(item.get('coverArt'))
|
image = connection.getCoverArtUrl(item.get('coverArt'))
|
||||||
artist_info = get_artist_info(item.get('id'))
|
artist_info = get_artist_info(item.get('id'))
|
||||||
artist_bio = artist_info.get('biography')
|
if(artist_info is None or artist_info == 'None'):
|
||||||
fanart = artist_info.get('largeImageUrl')
|
artist_lbl = '%s' % (item.get('name'))
|
||||||
|
else:
|
||||||
|
artist_lbl = '%s - %s' % (item.get('name'),artist_info)
|
||||||
|
print("Using label %s"%artist_lbl)
|
||||||
|
#artist_bio = artist_info.get('biography')
|
||||||
fanart = image
|
fanart = image
|
||||||
return {
|
return {
|
||||||
'label': get_starred_label(item.get('id'),item.get('name')),
|
'label': get_starred_label(item.get('id'),item.get('name')),
|
||||||
|
@ -799,11 +800,13 @@ def get_entry_artist(item,params):
|
||||||
'info': {
|
'info': {
|
||||||
'music': { ##http://romanvm.github.io/Kodistubs/_autosummary/xbmcgui.html#xbmcgui.ListItem.setInfo
|
'music': { ##http://romanvm.github.io/Kodistubs/_autosummary/xbmcgui.html#xbmcgui.ListItem.setInfo
|
||||||
'count': item.get('albumCount'),
|
'count': item.get('albumCount'),
|
||||||
'artist': item.get('name'),
|
'artist': artist_lbl,
|
||||||
#'title': "testtitle",
|
#'title': 'testtitle',
|
||||||
#'album': "testalbum",
|
#'album': 'testalbum',
|
||||||
#'comment': "testcomment"
|
#'comment': 'testcomment',
|
||||||
'title': artist_bio
|
#'label' : 'testlabel',
|
||||||
|
#'label2' : 'testlabel2',
|
||||||
|
#'title': artist_info
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue