Example #1
0
 def lastCacheDate(self):
     cur = geocacher.db().cursor()
     cur.execute("SELECT MAX(found_date) FROM Caches WHERE found = 1")
     return textToDateTime(cur.fetchone()[0]).date()
Example #2
0
    def load(self, filename, fileUpdates={}, gpxFilename=None):
        '''
        Imports the given .gpx file into the database.

        Arguments
        filename: path to the file from which to import the cache information

        Keyword Arguments
        fileUpdates: Dictionary for adding updates to for reporting back to the user
        gpxFilename: filename to use in gpx source column if different from filename
        '''
        mode = geocacher.config().importMode
        userName = geocacher.config().GCUserName
        userId = geocacher.config().GCUserID

        # Load GPX file
        if os.path.isfile(filename):
            gpxDoc = ElementTree.parse(filename).getroot()
            # Determine the file version
            schema = gpxDoc.attrib[
                '{http://www.w3.org/2001/XMLSchema-instance}schemaLocation']
            if schema.rfind('http://www.groundspeak.com/cache/1/0/1') >= 0:
                gpxVer = '1.0.1'
            elif schema.rfind('http://www.groundspeak.com/cache/1/0') >= 0:
                gpxVer = '1.0'
            else:
                gpxVer = '1.0'
            self.setNamespace(gpxVer)
            gpxDoc = ElementTree.parse(filename).getroot()
            NS = self.NS

            if gpxFilename == None:
                sourceFile = os.path.abspath(filename)
            else:
                sourceFile = gpxFilename + ":" + os.path.basename(filename)
        else:
            return (False, fileUpdates)
        # Get the date the GPX file was created
        try:
            gpxDate = textToDateTime('%s' % gpxDoc.find("gpx:time", NS).text)
            logging.debug('Date from File contents: %s' %
                          dateTimeToText(gpxDate))
        except:
            gpxDate = datetime.utcfromtimestamp(os.path.getmtime(filename))
            logging.debug('Date from file timestamp: %s' %
                          dateTimeToText(gpxDate))

        # Create list for extra points
        extraWpts = []

        # Find the waypoints and process them
        for wpt in gpxDoc.findall("gpx:wpt", NS):
            code = getTextFromPath(wpt, "gpx:name", NS)
            logging.debug(code)
            if code[:2] != "GC":
                extraWpts.append(wpt)
                continue
            lon = float(getAttribFromPath(wpt, ".", "lon", NS, '0.0'))
            lat = float(getAttribFromPath(wpt, ".", "lat", NS, '0.0'))
            id = int(getAttribFromPath(wpt, "gs:cache", "id", NS))
            available = textToBool(
                getAttribFromPath(wpt, "gs:cache", "available", NS, 'True'))
            archived = textToBool(
                getAttribFromPath(wpt, "gs:cache", "archived", NS, 'False'))
            name = getTextFromPath(wpt, "gpx:urlname", NS)
            url = getTextFromPath(wpt, "gpx:url", NS)
            placed = textToDateTime(getTextFromPath(wpt, "gpx:time", NS))
            placed_by = getTextFromPath(wpt, "gs:cache//gs:placed_by", NS)
            owner = getTextFromPath(wpt, "gs:cache//gs:owner", NS)
            owner_id = int(
                getAttribFromPath(wpt, "gs:cache//gs:owner", "id", NS))
            cachetype = getTextFromPath(wpt, "gs:cache//gs:type", NS)
            container = getTextFromPath(wpt, "gs:cache//gs:container", NS,
                                        "Not Specified")
            difficulty = float(
                getTextFromPath(wpt, "gs:cache//gs:difficulty", NS, "1"))
            terrain = float(
                getTextFromPath(wpt, "gs:cache//gs:terrain", NS, "1"))
            state = getTextFromPath(wpt, "gs:cache//gs:state", NS)
            country = getTextFromPath(wpt, "gs:cache//gs:country", NS)
            short_desc = getTextFromPath(wpt, "gs:cache//gs:short_description",
                                         NS, "")
            short_desc_html = textToBool(
                getAttribFromPath(wpt, "gs:cache//gs:short_description",
                                  "html", NS, "False"))
            long_desc = getTextFromPath(wpt, "gs:cache//gs:long_description",
                                        NS, "")
            long_desc_html = textToBool(
                getAttribFromPath(wpt, "gs:cache//gs:long_description", "html",
                                  NS, "False"))
            hints = getTextFromPath(wpt, "gs:cache//gs:encoded_hints", NS, "")

            if code in fileUpdates.keys():
                cacheUpdates = fileUpdates[code]
            else:
                cacheUpdates = {}

            cache = geocacher.db().getCacheByCode(code)
            if cache == None:
                cacheUpdates['change type'] = 'new'
                cacheUpdates['lat'] = [lat, '']
                cacheUpdates['lon'] = [lon, '']
                cacheUpdates['ci'] = [id, '']
                cacheUpdates['available'] = [available, '']
                cacheUpdates['archived'] = [archived, '']
                cacheUpdates['name'] = [name, '']
                cacheUpdates['url'] = [url, '']
                cacheUpdates['placed_by'] = [placed_by, '']
                cacheUpdates['owner'] = [owner, '']
                cacheUpdates['owner_id'] = [owner_id, '']
                cacheUpdates['type'] = [cachetype, '']
                cacheUpdates['container'] = [container, '']
                cacheUpdates['difficulty'] = [difficulty, '']
                cacheUpdates['terrain'] = [terrain, '']
                cacheUpdates['state'] = [state, '']
                cacheUpdates['country'] = [country, '']
                cacheUpdates['short_desc'] = [short_desc, '']
                cacheUpdates['short_desc_html'] = [short_desc_html, '']
                cacheUpdates['long_desc'] = [long_desc, '']
                cacheUpdates['long_desc_html'] = [long_desc_html, '']
                cacheUpdates['encoded_hints'] = [hints, '']
                cacheUpdates['gpx_date'] = [gpxDate, '']
                cache = geocacher.db().addCache(
                    code,
                    lat=lat,
                    lon=lon,
                    id=id,
                    available=available,
                    archived=archived,
                    name=name,
                    url=url,
                    placed=placed,
                    placed_by=placed_by,
                    owner=owner,
                    owner_id=owner_id,
                    type=cachetype,
                    container=container,
                    difficulty=difficulty,
                    terrain=terrain,
                    state=state,
                    country=country,
                    short_desc=short_desc,
                    short_desc_html=short_desc_html,
                    long_desc=long_desc,
                    long_desc_html=long_desc_html,
                    encoded_hints=hints,
                    gpx_date=gpxDate)

            elif 'change type' not in cacheUpdates.keys():
                cacheUpdates['change type'] = 'update'
            if ((cache.gpx_date <= gpxDate and mode == "update")
                    or mode == "replace"):
                if cache.lon != lon:
                    cacheUpdates['lon'] = [lon, cache.lon]
                    cache.lon = lon
                if cache.lat != lat:
                    cacheUpdates['lat'] = [lat, cache.lat]
                    cache.lat = lat
                if cache.id != id:
                    cacheUpdates['available'] = [cache.available, available]
                    cache.id = id
                if cache.archived != archived:
                    cacheUpdates['archived'] = [archived, cache.archived]
                    cache.archived = archived
                if cache.name != name:
                    cacheUpdates['name'] = [name, cache.name]
                    cache.name = name
                if cache.url != url:
                    cacheUpdates['url'] = [url, cache.url]
                    cache.url = url
                if cache.placed_by != placed_by:
                    cacheUpdates['placed_by'] = [placed_by, cache.placed_by]
                    cache.placed_by = placed_by
                if cache.owner != owner:
                    cacheUpdates['owner'] = [owner, cache.owner]
                    cache.owner = owner
                if cache.owner_id != owner_id:
                    cacheUpdates['owner_id'] = [owner_id, cache.owner_id]
                    cache.owner_id = owner_id
                if cache.type != cachetype:
                    cacheUpdates['type'] = [owner_id, cache.owner_id]
                    cache.type = cachetype
                if cache.container != container:
                    cacheUpdates['container'] = [container, cache.container]
                    cache.container = container
                if cache.difficulty != difficulty:
                    cacheUpdates['difficulty'] = [difficulty, cache.difficulty]
                    cache.difficulty = difficulty
                if cache.terrain != terrain:
                    cacheUpdates['terrain'] = [terrain, cache.terrain]
                    cache.terrain = terrain
                if cache.state != state:
                    cacheUpdates['state'] = [state, cache.state]
                    cache.state = state
                if cache.country != country:
                    cacheUpdates['country'] = [country, cache.country]
                    cache.country = country
                if cache.short_desc != short_desc:
                    cacheUpdates['short_desc'] = [short_desc, cache.short_desc]
                    cache.short_desc = short_desc
                if cache.short_desc_html != short_desc_html:
                    cacheUpdates['short_desc_html'] = [
                        short_desc_html, cache.short_desc_html
                    ]
                    cache.short_desc_html = short_desc_html
                if cache.long_desc != long_desc:
                    cacheUpdates['long_desc'] = [long_desc, cache.long_desc]
                    cache.long_desc = long_desc
                if cache.long_desc_html != long_desc_html:
                    cacheUpdates['long_desc_html'] = [
                        long_desc_html, cache.long_desc_html
                    ]
                if cache.encoded_hints != hints:
                    cacheUpdates['encoded_hints'] = [
                        hints, cache.encoded_hints
                    ]
                    cache.encoded_hints = hints

                if gpxVer == '1.0.1':
                    attribsUpdates = {}

                    wptAttribIds = []
                    for wptAttrib in wpt.findall(
                            "gs:cache//gs:attributes//gs:attribute", NS):
                        attribId = int(wptAttrib.attrib['id'])
                        attribInc = textToBool(wptAttrib.attrib['inc'])
                        attribDesc = wptAttrib.text
                        wptAttribIds.append(attribId)

                        attribUpdates = {}

                        attrib = cache.getAttributeById(attribId)

                        if attrib is None:
                            logging.debug(
                                'Attribute %i not found in existing data,  creating'
                                % attribId)
                            attribUpdates['inc'] = [attribInc, '']
                            attribUpdates['Description'] = [attribDesc, '']

                            attrib = cache.addAttribute(
                                attribId, attribInc, attribDesc)

                        else:
                            if attribInc != attrib.inc:
                                attribUpdates['inc'] = [attribInc, attrib.inc]
                                attrib.inc = attribInc
                            if attribDesc != attrib.description:
                                attribUpdates['Description'] = [attribDesc, '']
                                attrib.description = attribDesc

                        if len(attribUpdates) > 0:
                            attrib.save()
                            attribsUpdates[attribId] = attribUpdates

                    # Go through the cache attribs and delete any that are not
                    #listed in the wpt
                    for cacheAttribId in cache.getAttributeIds():
                        if not (cacheAttribId in wptAttribIds):
                            toDelete = cache.getAttributeById(cacheAttribId)
                            attribsUpdates[cacheAttribId] = {
                                _('Removed'): ['', '']
                            }
                            toDelete.delete()

                    if len(attribsUpdates) > 0:
                        cacheUpdates['Attributes'] = attribsUpdates

            # Always update Logs and travel bugs
            foundUpdated = False
            logsUpdates = {}
            for wptLog in wpt.findall("gs:cache//gs:logs//gs:log", NS):
                logId = int(getAttribFromPath(wptLog, '.', "id", NS))
                logDate = textToDateTime(getTextFromPath(
                    wptLog, "gs:date", NS))
                logType = getTextFromPath(wptLog, "gs:type", NS)
                logFinderId = int(
                    getAttribFromPath(wptLog, "gs:finder", "id", NS))
                logFinderName = getTextFromPath(wptLog, "gs:finder", NS)
                logEncoded = textToBool(
                    getAttribFromPath(wptLog, "gs:text", "encoded", NS,
                                      "False"))
                logText = getTextFromPath(wptLog, "gs:text", NS)

                logUpdates = {}

                log = cache.getLogById(logId)
                if log == None:
                    logging.debug(
                        'Log %i not forund in existing data, creating' % logId)
                    logUpdates['id'] = [logId, '']
                    logUpdates['date'] = [logDate, '']
                    logUpdates['type'] = [logType, '']
                    logUpdates['finder_id'] = [logFinderId, '']
                    logUpdates['finder_name'] = [logFinderName, '']
                    logUpdates['encoded'] = [logEncoded, '']
                    logUpdates['text'] = [logText, '']

                    log = cache.addLog(logId,
                                       date=logDate,
                                       logType=logType,
                                       finder_id=logFinderId,
                                       finder_name=logFinderName,
                                       encoded=logEncoded,
                                       text=logText)
                else:

                    logging.debug(
                        'Log %i found in existing data, checking data' % logId)
                    if logDate != log.date:
                        logUpdates['id'] = [logDate, log.date]
                        log.date = logDate
                    if logType != log.logType:
                        logUpdates['type'] = [logType, log.logType]
                        log.logType = logType
                    if logFinderId != log.finder_id:
                        logUpdates['finder_id'] = [logFinderId, log.finder_id]
                        log.finder_id = logFinderId
                    if logFinderName != log.finder_name:
                        logUpdates['finder_name'] = [
                            logFinderName, log.finder_name
                        ]
                        log.finder_name = logFinderName
                    if logEncoded != log.encoded:
                        logUpdates['encoded'] = [logEncoded, log.encoded]
                        log.encoded = logEncoded
                    if logText != log.text:
                        logUpdates['text'] = [logText, log.text]
                        log.text = logText
                if len(logUpdates) > 0:
                    log.save()
                    logsUpdates[logId] = logUpdates
                    # Update Own find details if this is the first log with changes
                    # in it that is of the "Found it" type and the finderId or
                    # finderName matches the users values
                    if ((not foundUpdated) and
                        (logFinderId == userId or logFinderName == userName)):
                        logging.debug('User ID or Name match for log id %i' %
                                      logId)
                        if logType in ['Found it', 'Attended']:
                            logging.debug('Log type is found or attended')
                            if not cache.found:
                                cacheUpdates['found'] = [True, False]
                                cache.found = True
                            if cache.found_date != logDate:
                                cacheUpdates['found_date'] = [
                                    logDate, cache.found_date
                                ]
                                cache.found_date = logDate
                            foundUpdated = True
                        elif logType == "Didn't find it":
                            logging.debug('Log type is DNF')
                            if not cache.dnf:
                                cacheUpdates['dnf'] = [True, False]
                                cache.dnf = True
                            if cache.dnf_date != logDate:
                                cacheUpdates['dnf_date'] = [
                                    logDate, cache.dnf_date
                                ]
                                cache.dnf_date = logDate
                            foundUpdated = True
                        if foundUpdated:
                            if cache.own_log_id != logId:
                                cacheUpdates['own_log_id'] = [
                                    logId, cache.own_log_id
                                ]
                                cache.own_log_id = logId
                                cache.refreshOwnLog()
            if len(logsUpdates) > 0:
                cacheUpdates['Logs'] = logsUpdates

            tbUpdates = {}
            wptTbRefs = []
            cacheTbRefs = cache.getTravelBugRefs()
            for wptTb in wpt.findall('gs:cache//gs:travelbugs//gs:travelbug',
                                     NS):
                wptTbRef = wptTb.attrib['ref']
                wptTbRefs.append(wptTbRef)
                wptTbId = wptTb.attrib['id']
                wptTbName = getTextFromPath(wptTb, 'gs:name', NS)
                if not (wptTbRef in cacheTbRefs):
                    tbUpdates[wptTbRef + ' ' + wptTbName] = [_('Added'), '']
                    cacheTb = cache.addTravelBug(wptTbRef,
                                                 id=wptTbId,
                                                 name=wptTbName)
                else:
                    cacheTb = cache.getTravelBugByRef(wptTbRef)
                    if cacheTb.name != wptTbName:
                        tbUpdates[wptTbRef + ' ' +
                                  wptTbName] = [cacheTb.name, wptTbName]
                        cacheTb.name = wptTbName
                        cacheTb.save()
            # Go through the list of travel bugs in the cache and delete any
            # that are not listed in the wpt
            for cacheTbRef in cacheTbRefs:
                if not (cacheTbRef in wptTbRefs):
                    toDelete = cache.getTravelBugByRef(cacheTbRef)
                    tbUpdates[cacheTbRef + ' ' +
                              toDelete.name] = [_('Removed'), '']
                    toDelete.delete()
            if len(tbUpdates) > 0:
                cacheUpdates['Travel Bugs'] = tbUpdates

            # Always update the gpx date and source file name even if no changes
            cache.gpx_date = gpxDate
            cache.source = sourceFile
            cache.save()

            if len(cacheUpdates) > 1:
                fileUpdates[code] = cacheUpdates

        for wpt in extraWpts:
            lon = float(getAttribFromPath(wpt, ".", "lon", NS, '0.0'))
            lat = float(getAttribFromPath(wpt, ".", "lat", NS, '0.0'))
            id = getTextFromPath(wpt, 'gpx:name', NS)
            time = textToDateTime(getTextFromPath(wpt, 'gpx:time', NS))
            cmt = getTextFromPath(wpt, 'gpx:cmt', NS, '')
            name = getTextFromPath(wpt, 'gpx:desc', NS)
            url = getTextFromPath(wpt, 'gpx:url', NS)
            sym = getTextFromPath(wpt, 'gpx:sym', NS)
            cacheCode = 'GC' + id[2:]
            cache = geocacher.db().getCacheByCode(cacheCode)
            if cache is not None:
                if cacheCode in fileUpdates.keys():
                    cacheUpdates = fileUpdates[cacheCode]
                else:
                    cacheUpdates = {}
                    cacheUpdates['change type'] = _('update')
                addWaypoint = cache.getAddWaypointByCode(id)
                addWptUpdates = {}
                if 'Add Wpts' in cacheUpdates.keys():
                    if id in cacheUpdates['Add Wpts'].keys():
                        addWptUpdates = cacheUpdates['Add Wpts'][id]
                if addWaypoint is None:
                    addWaypoint = cache.addAddWaypoint(id,
                                                       lat=lat,
                                                       lon=lon,
                                                       name=name,
                                                       url=url,
                                                       time=time,
                                                       cmt=cmt,
                                                       sym=sym)
                    addWptUpdates['id'] = [id, '']
                    addWptUpdates['lat'] = [lat, '']
                    addWptUpdates['lon'] = [lon, '']
                    addWptUpdates['name'] = [name, '']
                    addWptUpdates['url'] = [url, '']
                    addWptUpdates['time'] = [time, '']
                    addWptUpdates['cmt'] = [cmt, '']
                    addWptUpdates['sym'] = [sym, '']
                else:
                    if addWaypoint.lat != lat:
                        addWptUpdates['lat'] = [lat, addWaypoint.lat]
                        addWaypoint.lat = lat
                    if addWaypoint.lon != lon:
                        addWptUpdates['lon'] = [lon, addWaypoint.lon]
                        addWaypoint.lon = lon
                    if addWaypoint.name != name:
                        addWptUpdates['name'] = [name, addWaypoint.name]
                        addWaypoint.name = name
                    if addWaypoint.url != url:
                        addWptUpdates['url'] = [url, addWaypoint.url]
                        addWaypoint.url = url
                    if addWaypoint.time != time:
                        addWptUpdates['time'] = [time, addWaypoint.time]
                        addWaypoint.time = time
                    if addWaypoint.cmt != cmt:
                        addWptUpdates['cmt'] = [cmt, addWaypoint.cmt]
                        addWaypoint.cmt = cmt
                    if addWaypoint.sym != sym:
                        addWptUpdates['sym'] = [sym, addWaypoint.sym]
                        addWaypoint.sym = sym
                if len(addWptUpdates) > 0:
                    cache.gpx_date = gpxDate
                    cache.source = os.path.abspath(filename)
                    if 'Add Wpts' in cacheUpdates.keys():
                        cacheUpdates['Add Wpts'][id] = addWptUpdates
                    else:
                        cacheUpdates['Add Wpts'] = {id: addWptUpdates}
                    addWaypoint.save()
                    cache.save()
                    fileUpdates[cacheCode] = cacheUpdates
        if len(fileUpdates) > 0:
            geocacher.db().commit()

        return (True, fileUpdates)
Example #3
0
    def load(self,filename,fileUpdates={},gpxFilename = None):
        '''
        Imports the given .gpx file into the database.

        Arguments
        filename: path to the file from which to import the cache information

        Keyword Arguments
        fileUpdates: Dictionary for adding updates to for reporting back to the user
        gpxFilename: filename to use in gpx source column if different from filename
        '''
        mode = geocacher.config().importMode
        userName = geocacher.config().GCUserName
        userId = geocacher.config().GCUserID

        # Load GPX file
        if os.path.isfile(filename):
            gpxDoc = ElementTree.parse(filename).getroot()
            # Determine the file version
            schema = gpxDoc.attrib['{http://www.w3.org/2001/XMLSchema-instance}schemaLocation']
            if schema.rfind('http://www.groundspeak.com/cache/1/0/1') >= 0:
                gpxVer = '1.0.1'
            elif schema.rfind('http://www.groundspeak.com/cache/1/0') >= 0:
                gpxVer = '1.0'
            else:
                gpxVer = '1.0'
            self.setNamespace(gpxVer)
            gpxDoc = ElementTree.parse(filename).getroot()
            NS = self.NS

            if gpxFilename == None:
                sourceFile = os.path.abspath(filename)
            else:
                sourceFile = gpxFilename + ":" + os.path.basename(filename)
        else:
            return (False, fileUpdates)
        # Get the date the GPX file was created
        try:
            gpxDate = textToDateTime('%s' % gpxDoc.find("gpx:time", NS).text)
            logging.debug('Date from File contents: %s' % dateTimeToText(gpxDate))
        except:
            gpxDate = datetime.utcfromtimestamp(os.path.getmtime(filename))
            logging.debug('Date from file timestamp: %s' % dateTimeToText(gpxDate))

        # Create list for extra points
        extraWpts = []

        # Find the waypoints and process them
        for wpt in gpxDoc.findall("gpx:wpt", NS):
            code = getTextFromPath(wpt,"gpx:name",NS)
            logging.debug(code)
            if code[:2] !="GC":
                extraWpts.append(wpt)
                continue
            lon = float(getAttribFromPath(wpt,".","lon",NS,'0.0'))
            lat = float(getAttribFromPath(wpt,".","lat",NS,'0.0'))
            id = int(getAttribFromPath(wpt,"gs:cache","id",NS))
            available = textToBool(getAttribFromPath(wpt,"gs:cache","available",NS,'True'))
            archived = textToBool(getAttribFromPath(wpt,"gs:cache","archived",NS,'False'))
            name = getTextFromPath(wpt,"gpx:urlname",NS)
            url = getTextFromPath(wpt,"gpx:url",NS)
            placed = textToDateTime(getTextFromPath(wpt,"gpx:time",NS))
            placed_by = getTextFromPath(wpt,"gs:cache//gs:placed_by",NS)
            owner = getTextFromPath(wpt,"gs:cache//gs:owner",NS)
            owner_id = int(getAttribFromPath(wpt,"gs:cache//gs:owner","id",NS))
            cachetype = getTextFromPath(wpt,"gs:cache//gs:type",NS)
            container = getTextFromPath(wpt,"gs:cache//gs:container",NS,"Not Specified")
            difficulty = float(getTextFromPath(wpt,"gs:cache//gs:difficulty",NS,"1"))
            terrain = float(getTextFromPath(wpt,"gs:cache//gs:terrain",NS,"1"))
            state = getTextFromPath(wpt,"gs:cache//gs:state",NS)
            country = getTextFromPath(wpt,"gs:cache//gs:country",NS)
            short_desc = getTextFromPath(wpt,"gs:cache//gs:short_description",NS,"")
            short_desc_html = textToBool(getAttribFromPath(wpt,"gs:cache//gs:short_description","html",NS,"False"))
            long_desc = getTextFromPath(wpt,"gs:cache//gs:long_description",NS,"")
            long_desc_html = textToBool(getAttribFromPath(wpt,"gs:cache//gs:long_description","html",NS,"False"))
            hints = getTextFromPath(wpt,"gs:cache//gs:encoded_hints",NS,"")

            if code in fileUpdates.keys():
                cacheUpdates = fileUpdates[code]
            else:
                cacheUpdates = {}

            cache = geocacher.db().getCacheByCode(code)
            if cache==None:
                cacheUpdates['change type'] = 'new'
                cacheUpdates['lat'] = [lat,'']
                cacheUpdates['lon'] = [lon,'']
                cacheUpdates['ci'] = [id,'']
                cacheUpdates['available'] = [available,'']
                cacheUpdates['archived'] = [archived,'']
                cacheUpdates['name'] = [name,'']
                cacheUpdates['url'] = [url,'']
                cacheUpdates['placed_by'] = [placed_by,'']
                cacheUpdates['owner'] = [owner,'']
                cacheUpdates['owner_id'] = [owner_id,'']
                cacheUpdates['type'] = [cachetype,'']
                cacheUpdates['container'] = [container,'']
                cacheUpdates['difficulty'] = [difficulty,'']
                cacheUpdates['terrain'] = [terrain,'']
                cacheUpdates['state'] = [state,'']
                cacheUpdates['country'] = [country,'']
                cacheUpdates['short_desc'] = [short_desc,'']
                cacheUpdates['short_desc_html'] = [short_desc_html,'']
                cacheUpdates['long_desc'] = [long_desc,'']
                cacheUpdates['long_desc_html'] = [long_desc_html,'']
                cacheUpdates['encoded_hints'] = [hints,'']
                cacheUpdates['gpx_date'] = [gpxDate,'']
                cache = geocacher.db().addCache(code,lat=lat,lon=lon,id=id,
                                    available=available,archived=archived,
                                    name=name,url=url,
                                    placed=placed,placed_by=placed_by,
                                    owner=owner,owner_id=owner_id,
                                    type=cachetype,container=container,
                                    difficulty=difficulty,terrain=terrain,
                                    state=state,country=country,
                                    short_desc=short_desc,
                                    short_desc_html=short_desc_html,
                                    long_desc=long_desc,
                                    long_desc_html=long_desc_html,
                                    encoded_hints=hints,gpx_date=gpxDate)



            elif 'change type' not in cacheUpdates.keys():
                cacheUpdates['change type'] = 'update'
            if ((cache.gpx_date<=gpxDate and mode=="update") or mode=="replace"):
                if cache.lon != lon:
                    cacheUpdates['lon'] = [lon,cache.lon]
                    cache.lon = lon
                if cache.lat != lat:
                    cacheUpdates['lat'] = [lat,cache.lat]
                    cache.lat = lat
                if cache.id != id:
                    cacheUpdates['available'] = [cache.available,available]
                    cache.id = id
                if cache.archived != archived:
                    cacheUpdates['archived'] = [archived,cache.archived]
                    cache.archived = archived
                if cache.name != name:
                    cacheUpdates['name'] = [name,cache.name]
                    cache.name = name
                if cache.url != url:
                    cacheUpdates['url'] = [url,cache.url]
                    cache.url = url
                if cache.placed_by != placed_by:
                    cacheUpdates['placed_by'] = [placed_by,cache.placed_by]
                    cache.placed_by = placed_by
                if cache.owner != owner:
                    cacheUpdates['owner'] = [owner,cache.owner]
                    cache.owner = owner
                if cache.owner_id != owner_id:
                    cacheUpdates['owner_id'] = [owner_id,cache.owner_id]
                    cache.owner_id = owner_id
                if cache.type != cachetype:
                    cacheUpdates['type'] = [owner_id,cache.owner_id]
                    cache.type = cachetype
                if cache.container != container:
                    cacheUpdates['container'] = [container,cache.container]
                    cache.container = container
                if cache.difficulty != difficulty:
                    cacheUpdates['difficulty'] = [difficulty,cache.difficulty]
                    cache.difficulty = difficulty
                if cache.terrain != terrain:
                    cacheUpdates['terrain'] = [terrain,cache.terrain]
                    cache.terrain = terrain
                if cache.state != state:
                    cacheUpdates['state'] = [state,cache.state]
                    cache.state = state
                if cache.country != country:
                    cacheUpdates['country'] = [country,cache.country]
                    cache.country = country
                if cache.short_desc != short_desc:
                    cacheUpdates['short_desc'] = [short_desc,cache.short_desc]
                    cache.short_desc = short_desc
                if cache.short_desc_html != short_desc_html:
                    cacheUpdates['short_desc_html'] = [short_desc_html,
                                                       cache.short_desc_html]
                    cache.short_desc_html = short_desc_html
                if cache.long_desc != long_desc:
                    cacheUpdates['long_desc'] = [long_desc,cache.long_desc]
                    cache.long_desc = long_desc
                if cache.long_desc_html != long_desc_html:
                    cacheUpdates['long_desc_html'] = [long_desc_html,
                                                      cache.long_desc_html]
                if cache.encoded_hints != hints:
                    cacheUpdates['encoded_hints'] = [hints,cache.encoded_hints]
                    cache.encoded_hints = hints

                if gpxVer == '1.0.1':
                    attribsUpdates = {}

                    wptAttribIds = []
                    for wptAttrib in wpt.findall("gs:cache//gs:attributes//gs:attribute", NS):
                        attribId = int(wptAttrib.attrib['id'])
                        attribInc = textToBool(wptAttrib.attrib['inc'])
                        attribDesc = wptAttrib.text
                        wptAttribIds.append(attribId)

                        attribUpdates = {}

                        attrib = cache.getAttributeById(attribId)

                        if attrib is None:
                            logging.debug('Attribute %i not found in existing data,  creating' % attribId)
                            attribUpdates['inc'] = [attribInc, '']
                            attribUpdates['Description'] = [attribDesc, '']

                            attrib = cache.addAttribute(attribId, attribInc, attribDesc)

                        else:
                            if attribInc != attrib.inc:
                                attribUpdates['inc'] = [attribInc, attrib.inc]
                                attrib.inc = attribInc
                            if attribDesc != attrib.description:
                                attribUpdates['Description'] = [attribDesc, '']
                                attrib.description = attribDesc

                        if len(attribUpdates) > 0:
                            attrib.save()
                            attribsUpdates[attribId] = attribUpdates

                    # Go through the cache attribs and delete any that are not
                    #listed in the wpt
                    for cacheAttribId in cache.getAttributeIds():
                        if not(cacheAttribId in wptAttribIds):
                            toDelete = cache.getAttributeById(cacheAttribId)
                            attribsUpdates[cacheAttribId] = {_('Removed'):['','']}
                            toDelete.delete()

                    if len(attribsUpdates) > 0:
                        cacheUpdates['Attributes'] = attribsUpdates

            # Always update Logs and travel bugs
            foundUpdated=False
            logsUpdates = {}
            for wptLog in wpt.findall("gs:cache//gs:logs//gs:log", NS):
                logId = int(getAttribFromPath(wptLog, '.', "id",NS))
                logDate = textToDateTime(getTextFromPath(wptLog, "gs:date",NS))
                logType = getTextFromPath(wptLog, "gs:type",NS)
                logFinderId = int(getAttribFromPath(wptLog, "gs:finder", "id", NS))
                logFinderName = getTextFromPath(wptLog, "gs:finder",NS)
                logEncoded = textToBool(getAttribFromPath(wptLog, "gs:text", "encoded", NS, "False"))
                logText = getTextFromPath(wptLog, "gs:text",NS)

                logUpdates = {}

                log = cache.getLogById(logId)
                if  log==None:
                    logging.debug('Log %i not forund in existing data, creating' % logId)
                    logUpdates['id'] = [logId,'']
                    logUpdates['date'] = [logDate,'']
                    logUpdates['type'] = [logType,'']
                    logUpdates['finder_id'] = [logFinderId,'']
                    logUpdates['finder_name'] = [logFinderName,'']
                    logUpdates['encoded'] = [logEncoded,'']
                    logUpdates['text'] = [logText,'']

                    log = cache.addLog(logId,date=logDate,logType=logType,
                    finder_id=logFinderId,finder_name=logFinderName,
                    encoded=logEncoded,text=logText)
                else:

                    logging.debug('Log %i found in existing data, checking data' % logId)
                    if logDate != log.date:
                        logUpdates['id'] = [logDate,log.date]
                        log.date = logDate
                    if logType != log.logType:
                        logUpdates['type'] = [logType,log.logType]
                        log.logType = logType
                    if logFinderId != log.finder_id:
                        logUpdates['finder_id'] = [logFinderId,log.finder_id]
                        log.finder_id = logFinderId
                    if logFinderName != log.finder_name:
                        logUpdates['finder_name'] = [logFinderName,log.finder_name]
                        log.finder_name = logFinderName
                    if logEncoded != log.encoded:
                        logUpdates['encoded'] = [logEncoded,log.encoded]
                        log.encoded = logEncoded
                    if logText != log.text:
                        logUpdates['text'] = [logText,log.text]
                        log.text = logText
                if len(logUpdates) > 0:
                    log.save()
                    logsUpdates[logId] = logUpdates
                    # Update Own find details if this is the first log with changes
                    # in it that is of the "Found it" type and the finderId or
                    # finderName matches the users values
                    if ((not foundUpdated) and(logFinderId == userId or
                                               logFinderName == userName)):
                        logging.debug('User ID or Name match for log id %i' % logId)
                        if logType in ['Found it', 'Attended']:
                            logging.debug('Log type is found or attended')
                            if not cache.found:
                                cacheUpdates['found'] = [True,False]
                                cache.found = True
                            if cache.found_date != logDate:
                                cacheUpdates['found_date'] = [logDate,cache.found_date]
                                cache.found_date = logDate
                            foundUpdated = True
                        elif logType == "Didn't find it":
                            logging.debug('Log type is DNF')
                            if not cache.dnf:
                                cacheUpdates['dnf'] = [True,False]
                                cache.dnf = True
                            if cache.dnf_date != logDate:
                                cacheUpdates['dnf_date'] = [logDate,cache.dnf_date]
                                cache.dnf_date = logDate
                            foundUpdated = True
                        if foundUpdated:
                            if cache.own_log_id != logId:
                                cacheUpdates['own_log_id'] = [logId,cache.own_log_id]
                                cache.own_log_id = logId
                                cache.refreshOwnLog()
            if len(logsUpdates) > 0:
                cacheUpdates['Logs'] = logsUpdates

            tbUpdates = {}
            wptTbRefs = []
            cacheTbRefs = cache.getTravelBugRefs()
            for wptTb in wpt.findall('gs:cache//gs:travelbugs//gs:travelbug', NS):
                wptTbRef = wptTb.attrib['ref']
                wptTbRefs.append(wptTbRef)
                wptTbId = wptTb.attrib['id']
                wptTbName = getTextFromPath(wptTb,'gs:name',NS)
                if not (wptTbRef in cacheTbRefs):
                    tbUpdates[wptTbRef + ' ' +wptTbName] = [_('Added'),'']
                    cacheTb = cache.addTravelBug(wptTbRef,id=wptTbId,name=wptTbName)
                else:
                    cacheTb = cache.getTravelBugByRef(wptTbRef)
                    if cacheTb.name != wptTbName:
                        tbUpdates[wptTbRef + ' ' +wptTbName] = [cacheTb.name, wptTbName]
                        cacheTb.name = wptTbName
                        cacheTb.save()
            # Go through the list of travel bugs in the cache and delete any
            # that are not listed in the wpt
            for cacheTbRef in cacheTbRefs:
                if not(cacheTbRef in wptTbRefs):
                    toDelete = cache.getTravelBugByRef(cacheTbRef)
                    tbUpdates[cacheTbRef + ' ' +toDelete.name] = [_('Removed'),'']
                    toDelete.delete()
            if len(tbUpdates) > 0:
                cacheUpdates['Travel Bugs'] = tbUpdates

            # Always update the gpx date and source file name even if no changes
            cache.gpx_date = gpxDate
            cache.source = sourceFile
            cache.save()

            if len(cacheUpdates) > 1:
                fileUpdates[code] = cacheUpdates

        for wpt in extraWpts:
            lon = float(getAttribFromPath(wpt,".","lon",NS,'0.0'))
            lat = float(getAttribFromPath(wpt,".","lat",NS,'0.0'))
            id = getTextFromPath(wpt,'gpx:name',NS)
            time = textToDateTime(getTextFromPath(wpt,'gpx:time',NS))
            cmt = getTextFromPath(wpt,'gpx:cmt',NS,'')
            name = getTextFromPath(wpt,'gpx:desc',NS)
            url = getTextFromPath(wpt,'gpx:url',NS)
            sym = getTextFromPath(wpt,'gpx:sym',NS)
            cacheCode = 'GC'+id[2:]
            cache = geocacher.db().getCacheByCode(cacheCode)
            if cache is not None:
                if cacheCode in fileUpdates.keys():
                    cacheUpdates = fileUpdates[cacheCode]
                else:
                    cacheUpdates = {}
                    cacheUpdates['change type'] = _('update')
                addWaypoint = cache.getAddWaypointByCode(id)
                addWptUpdates = {}
                if 'Add Wpts' in cacheUpdates.keys():
                    if id in cacheUpdates['Add Wpts'].keys():
                        addWptUpdates =cacheUpdates['Add Wpts'][id]
                if addWaypoint is None:
                    addWaypoint = cache.addAddWaypoint(id,
                                                       lat=lat,
                                                       lon=lon,
                                                       name=name,
                                                       url=url,
                                                       time=time,
                                                       cmt=cmt,
                                                       sym=sym)
                    addWptUpdates['id'] = [id,'']
                    addWptUpdates['lat'] = [lat,'']
                    addWptUpdates['lon'] = [lon,'']
                    addWptUpdates['name'] = [name,'']
                    addWptUpdates['url'] = [url,'']
                    addWptUpdates['time'] = [time,'']
                    addWptUpdates['cmt'] = [cmt,'']
                    addWptUpdates['sym'] = [sym,'']
                else:
                    if addWaypoint.lat != lat:
                        addWptUpdates['lat'] = [lat,addWaypoint.lat]
                        addWaypoint.lat = lat
                    if addWaypoint.lon != lon:
                        addWptUpdates['lon'] = [lon,addWaypoint.lon]
                        addWaypoint.lon = lon
                    if addWaypoint.name != name:
                        addWptUpdates['name'] = [name,addWaypoint.name]
                        addWaypoint.name = name
                    if addWaypoint.url != url:
                        addWptUpdates['url'] = [url,addWaypoint.url]
                        addWaypoint.url = url
                    if addWaypoint.time != time:
                        addWptUpdates['time'] = [time,addWaypoint.time]
                        addWaypoint.time = time
                    if addWaypoint.cmt != cmt:
                        addWptUpdates['cmt'] = [cmt,addWaypoint.cmt]
                        addWaypoint.cmt = cmt
                    if addWaypoint.sym != sym:
                        addWptUpdates['sym'] = [sym,addWaypoint.sym]
                        addWaypoint.sym = sym
                if len(addWptUpdates) > 0:
                    cache.gpx_date = gpxDate
                    cache.source = os.path.abspath(filename)
                    if 'Add Wpts' in cacheUpdates.keys():
                        cacheUpdates['Add Wpts'][id] = addWptUpdates
                    else:
                        cacheUpdates['Add Wpts'] = {id: addWptUpdates}
                    addWaypoint.save()
                    cache.save()
                    fileUpdates[cacheCode] = cacheUpdates
        if len(fileUpdates) > 0:
            geocacher.db().commit()

        return (True,fileUpdates)
Example #4
0
 def lastCacheDate(self):
     cur = geocacher.db().cursor()
     cur.execute("SELECT MAX(found_date) FROM Caches WHERE found = 1")
     return textToDateTime(cur.fetchone()[0]).date()