summaryrefslogtreecommitdiff
path: root/plugin.video.embycon/resources/lib/datamanager.py
blob: f5f69b5bdb2378d58ba1cd3f902c8d02efcb30b7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# Gnu General Public License - see LICENSE.TXT

import hashlib
import os
import threading
import json
import encodings

import xbmcaddon
import xbmc

from downloadutils import DownloadUtils
from simple_logging import SimpleLogging
from utils import getChecksum
from kodi_utils import HomeWindow

log = SimpleLogging(__name__)


class DataManager():
    cacheDataResult = None
    dataUrl = None
    cacheDataPath = None
    canRefreshNow = False

    def __init__(self, *args):
        log.debug("DataManager __init__")

    def getCacheValidatorFromData(self, result):
        key = 'Items'
        results = result.get(key)
        if results is None:
            key = 'SearchHints'
            results = result.get(key)
            if results is None:
                results = []

        itemCount = 0
        dataHashString = ""

        for item in results:
            item_hash_string = getChecksum(item)
            item_hash_string = str(itemCount) + "_" + key + "_" + item.get("Name", "-") + "_" + item_hash_string + "|"
            log.debug("ITEM_HASH: " + item_hash_string)
            dataHashString += item_hash_string
            itemCount += 1

        # hash the data
        dataHashString = dataHashString.encode("UTF-8")
        m = hashlib.md5()
        m.update(dataHashString)
        validatorString = m.hexdigest()

        log.debug("getCacheValidatorFromData : RawData  : " + dataHashString)
        log.debug("getCacheValidatorFromData : hashData : " + validatorString)

        return validatorString

    def loadJasonData(self, jsonData):
        return json.loads(jsonData)

    def GetContent(self, url):

        __addon__ = xbmcaddon.Addon(id='plugin.video.embycon')
        use_cache_system = __addon__.getSetting('cacheEmbyData') == "true"

        if use_cache_system == False:
            # dont use cache system at all, just get the result and return
            log.debug("GetContent - Not using cache system")
            jsonData = DownloadUtils().downloadUrl(url, suppress=False, popup=1)
            result = self.loadJasonData(jsonData)
            log.debug("Returning Loaded Result")
            return result

        # first get the url hash
        m = hashlib.md5()
        m.update(url)
        urlHash = m.hexdigest()

        # build cache data path

        __addondir__ = xbmc.translatePath(__addon__.getAddonInfo('profile'))
        if not os.path.exists(os.path.join(__addondir__, "cache")):
            os.makedirs(os.path.join(__addondir__, "cache"))
        cacheDataPath = os.path.join(__addondir__, "cache", urlHash)

        log.debug("Cache_Data_Manager:" + cacheDataPath)

        # are we forcing a reload
        WINDOW = HomeWindow()
        force_data_reload = WINDOW.getProperty("force_data_reload") == "true"
        WINDOW.clearProperty("force_data_reload")

        if os.path.exists(cacheDataPath) and not force_data_reload:
            # load data from cache if it is available and trigger a background
            # verification process to test cache validity   
            log.debug("Loading Cached File")
            with open(cacheDataPath, 'r') as f:
                result = self.loadJasonData(f.read())

            # start a worker thread to process the cache validity
            self.cacheDataResult = result
            self.dataUrl = url
            self.cacheDataPath = cacheDataPath
            actionThread = CacheManagerThread()
            actionThread.setCacheData(self)
            actionThread.start()

            log.debug("Returning Cached Result")
            return result
        else:
            # no cache data so load the url and save it
            jsonData = DownloadUtils().downloadUrl(url, suppress=False, popup=1)
            log.debug("Loading URL and saving to cache")
            with open(cacheDataPath, 'w') as f:
                f.write(jsonData)
            result = self.loadJasonData(jsonData)
            self.cacheManagerFinished = True
            log.debug("Returning Loaded Result")
            return result


class CacheManagerThread(threading.Thread):
    dataManager = None

    def __init__(self, *args):
        threading.Thread.__init__(self, *args)

    def setCacheData(self, data):
        self.dataManager = data

    def run(self):

        log.debug("CacheManagerThread Started")

        cacheValidatorString = self.dataManager.getCacheValidatorFromData(self.dataManager.cacheDataResult)
        log.debug("Cache Validator String (" + cacheValidatorString + ")")

        jsonData = DownloadUtils().downloadUrl(self.dataManager.dataUrl, suppress=False, popup=1)
        loadedResult = self.dataManager.loadJasonData(jsonData)
        loadedValidatorString = self.dataManager.getCacheValidatorFromData(loadedResult)
        log.debug("Loaded Validator String (" + loadedValidatorString + ")")

        # if they dont match then save the data and trigger a content reload
        if (cacheValidatorString != loadedValidatorString):
            log.debug("CacheManagerThread Saving new cache data and reloading container")
            with open(self.dataManager.cacheDataPath, 'w') as f:
                f.write(jsonData)

            # we need to refresh but will wait until the main function has finished
            loops = 0
            while (self.dataManager.canRefreshNow == False and loops < 200 and not xbmc.Monitor().abortRequested()):
                log.debug("Cache_Data_Manager: Not finished yet")
                xbmc.sleep(100)
                loops = loops + 1

            log.debug("Sending container refresh (" + str(loops) + ")")
            xbmc.executebuiltin("Container.Refresh")

        log.debug("CacheManagerThread Exited")