예제 #1
0
def read_index(filename):
    ''' process index file in default location. '''
    try:
        importedbotsindex, scriptname = botslib.botsimport('index')
        pluglist = importedbotsindex.plugins[:]
        if importedbotsindex.__name__ in sys.modules:
            del sys.modules[importedbotsindex.__name__]
    except:
        txt = botslib.txtexc()
        raise botslib.PluginError(
            _(u'Error in configuration index file. Nothing is written. Error:\n%(txt)s'
              ), {'txt': txt})
    else:
        botsglobal.logger.info(_(u'Configuration index file is OK.'))
        botsglobal.logger.info(_(u'Start writing to database.'))

    #write content of index file to the bots database
    try:
        read_index2database(pluglist)
    except:
        txt = botslib.txtexc()
        raise botslib.PluginError(
            _(u'Error writing configuration index to database. Nothing is written. Error:\n%(txt)s'
              ), {'txt': txt})
    else:
        botsglobal.logger.info(_(u'Writing to database is OK.'))
예제 #2
0
def writetodatabase(orgpluglist):
    #sanity checks on pluglist
    if not orgpluglist:  #list of plugins is empty: is OK. DO nothing
        return
    if not isinstance(orgpluglist, list):  #has to be a list!!
        raise Exception(
            _(u'plugins should be list of dicts. Nothing is written.'))
    for plug in orgpluglist:
        if not isinstance(plug, dict):
            raise botslib.PluginError(
                _(u'plugins should be list of dicts. Nothing is written.'))
        for key in plug.keys():
            if not isinstance(key, basestring):
                raise botslib.PluginError(
                    _('key of dict is not a string: "%s". Nothing is written.')
                    % (plug))
        if 'plugintype' not in plug:
            raise botslib.PluginError(
                _(u'"plugintype" missing in: "%s". Nothing is written.') %
                (plug))

    #in bots 1.*, partnrgroup was in seperate tabel; in bots 2.* partnergroup is in partner
    for plug in orgpluglist[:]:
        if plug['plugintype'] == 'partnergroup':
            for plugpartner in orgpluglist:
                if plugpartner['plugintype'] == 'partner' and plugpartner[
                        'idpartner'] == plug['idpartner']:
                    if 'group' in plugpartner:
                        plugpartner['group'].append(plug['idpartnergroup'])
                    else:
                        plugpartner['group'] = [plug['idpartnergroup']]
                    break

    #copy & filter orgpluglist; do plugtype specific adaptions
    pluglist = []
    for plug in orgpluglist:
        if plug['plugintype'] == 'ccode':  #add ccodetrigger.
            for seachccodetriggerplug in pluglist:
                if seachccodetriggerplug[
                        'plugintype'] == 'ccodetrigger' and seachccodetriggerplug[
                            'ccodeid'] == plug['ccodeid']:
                    break
            else:
                pluglist.append({
                    'plugintype': 'ccodetrigger',
                    'ccodeid': plug['ccodeid']
                })
        elif plug[
                'plugintype'] == 'translate':  #make some fields None instead of '' (translate formpartner, topartner)
            if not plug['frompartner']:
                plug['frompartner'] = None
            if not plug['topartner']:
                plug['topartner'] = None
        elif plug['plugintype'] in [
                'ta', 'filereport'
        ]:  #sqlite can have errortexts that are to long. Chop these
            plug['errortext'] = plug['errortext'][:2047]
        elif plug['plugintype'] == 'routes':
            plug['active'] = False
            if not 'defer' in plug:
                plug['defer'] = False
            else:
                if plug['defer'] is None:
                    plug['defer'] = False
        elif plug['plugintype'] == 'confirmrule':
            plug.pop('id', None)  #id is an artificial key, delete,
        elif plug['plugintype'] not in lijst:  #filter
            continue
        pluglist.append(plug)
    #sort pluglist: this is needed for relationships
    pluglist.sort(cmp=pluglistcmp, key=operator.itemgetter('plugintype'))
    #2nd sort:
    pluglist.sort(cmp=pluglistcmpisgroup)
    #~ for plug in pluglist:
    #~ print 'list:',plug

    for plug in pluglist:
        botsglobal.logger.info(u'    Start write to database for: "%s".' %
                               plug)
        #~ print '\nstart plug', plug
        table = django.db.models.get_model('bots', plug['plugintype'])
        #~ print table

        #delete fields not in model (create compatibility plugin-version)
        loopdictionary = plug.keys()
        for key in loopdictionary:
            try:
                table._meta.get_field(key)
            except django.db.models.fields.FieldDoesNotExist:
                del plug[key]
        #make right key(s)fields (in dict 'sleutel')
        pk = table._meta.pk.name
        if pk == 'id':
            sleutel = {}
            if table._meta.unique_together:
                for key in table._meta.unique_together[0]:
                    sleutel[key] = plug.pop(key)
        else:
            sleutel = {pk: plug.pop(pk)}
        #now we have:
        #- sleutel: unique key fields. mind: translate and confirmrule have empty 'sleutel' now
        #- plug: rest of database fields

        #get real column names for fields: for relational fields
        loopdictionary = plug.keys()
        for fieldname in loopdictionary:
            fieldobject = table._meta.get_field_by_name(fieldname)[0]
            try:
                if fieldobject.column != fieldname:
                    plug[fieldobject.column] = plug[fieldname]
                    del plug[fieldname]
                    #~ print 'replace _id for:',fieldname
            except:
                print 'no field column for:', fieldname
        #get real column names for fields in sleutel
        sleutelorg = sleutel.copy()
        loopdictionary = sleutel.keys()
        for fieldname in loopdictionary:
            fieldobject = table._meta.get_field_by_name(fieldname)[0]
            try:
                if fieldobject.column != fieldname:
                    sleutel[fieldobject.column] = sleutel[fieldname]
                    del sleutel[fieldname]
            except:
                print 'no field column for', fieldname

        #~ print 'plug attr',plug
        #~ print '**sleutel',sleutelorg

        if sleutelorg:  #translate and confirmrule have empty 'sleutel'
            checkifexistsindb = table.objects.filter(**sleutelorg).all()
            if len(checkifexistsindb) > 1:
                raise Exception('not unique?')
            elif len(checkifexistsindb) == 1:
                checkifexistsindb[0].delete()
                #~ print 'deleted old enty'
            botsglobal.logger.info(
                _(u'        Existing entry in database is deleted.'))

        dbobject = table(**sleutel)  #create db-object
        if 'idpartner' in sleutel:  #for partners, first the partner needs to be saved before groups can be made
            dbobject.save()
        for key, value in plug.items():
            setattr(dbobject, key, value)
        dbobject.save()
        botsglobal.logger.info(_(u'        Write to database is OK.'))
예제 #3
0
def load(pathzipfile):
    ''' process uploaded plugin. '''
    #test is valid zipfile
    if not zipfile.is_zipfile(pathzipfile):
        raise botslib.PluginError(_(u'Plugin is not a valid file.'))

    #read index file
    try:
        Zipimporter = zipimport.zipimporter(pathzipfile)
        importedbotsindex = Zipimporter.load_module('botsindex')
        pluglist = importedbotsindex.plugins[:]
        if 'botsindex' in sys.modules:
            del sys.modules['botsindex']
    except:
        txt = botslib.txtexc()
        raise botslib.PluginError(
            _(u'Error in plugin. Nothing is written. Error: "%s"') % (txt))
    else:
        botsglobal.logger.info(_(u'Plugin is OK.\nStart writing to database.'))

    #write content of index file to the bots database
    try:
        writetodatabase(pluglist)
    except:
        txt = botslib.txtexc()
        raise botslib.PluginError(
            'Error writing plugin to database. Nothing is written. Error: "%s"'
            % (txt))
    else:
        botsglobal.logger.info(
            u'Writing to database is OK.\nStart writing to files')

    #write files to the file system.
    try:
        warnrenamed = False  #to report in GUI files have been overwritten.
        z = zipfile.ZipFile(pathzipfile, mode="r")
        orgtargetpath = botsglobal.ini.get('directories', 'botspath')
        if (orgtargetpath[-1:] in (os.path.sep, os.path.altsep)
                and len(os.path.splitdrive(orgtargetpath)[1]) > 1):
            orgtargetpath = orgtargetpath[:-1]
        for f in z.infolist():
            if f.filename not in [
                    'botsindex.py', 'README', 'botssys/sqlitedb/botsdb',
                    'config/bots.ini'
            ] and os.path.splitext(f.filename)[1] not in ['.pyo', '.pyc']:
                #~ botsglobal.logger.info(u'filename in zip "%s".',f.filename)
                if f.filename[0] == '/':
                    targetpath = f.filename[1:]
                else:
                    targetpath = f.filename
                targetpath = targetpath.replace(
                    'usersys', botsglobal.ini.get('directories', 'usersysabs'),
                    1)
                targetpath = targetpath.replace(
                    'botssys', botsglobal.ini.get('directories', 'botssys'), 1)
                targetpath = botslib.join(orgtargetpath, targetpath)
                #targetpath is OK now.
                botsglobal.logger.info(_(u'    Start writing file: "%s".'),
                                       targetpath)

                if botslib.dirshouldbethere(os.path.dirname(targetpath)):
                    botsglobal.logger.info(
                        _(u'        Create directory "%s".'),
                        os.path.dirname(targetpath))
                if f.filename[
                        -1] == '/':  #check if this is a dir; if so continue
                    continue
                if os.path.isfile(targetpath):  #check if file already exists
                    try:  #this ***sometimes*** fails. (python25, for static/help/home.html...only there...)
                        os.rename(
                            targetpath,
                            targetpath + '.' + time.strftime('%Y%m%d%H%M%S'))
                        warnrenamed = True
                        botsglobal.logger.info(
                            _(u'        Renamed existing file "%(from)s" to "%(to)s".'
                              ), {
                                  'from': targetpath,
                                  'to':
                                  targetpath + time.strftime('%Y%m%d%H%M%S')
                              })
                    except:
                        pass
                source = z.read(f.filename)
                target = open(targetpath, "wb")
                target.write(source)
                target.close()
                botsglobal.logger.info(_(u'        File written: "%s".'),
                                       targetpath)
    except:
        txt = botslib.txtexc()
        z.close()
        raise botslib.PluginError(
            _(u'Error writing files to system. Nothing is written to database. Error: "%s"'
              ) % (txt))
    else:
        z.close()
        botsglobal.logger.info(_(u'Writing files to filesystem is OK.'))
        return warnrenamed
예제 #4
0
def writetodatabase(orgpluglist):
    #sanity checks on pluglist
    if not orgpluglist:  #list of plugins is empty: is OK. DO nothing
        return
    if not isinstance(orgpluglist, list):  #has to be a list!!
        raise botslib.PluginError(
            _(u'plugins should be list of dicts. Nothing is written.'))
    for plug in orgpluglist:
        if not isinstance(plug, dict):
            raise botslib.PluginError(
                _(u'plugins should be list of dicts. Nothing is written.'))
        for key in plug.keys():
            if not isinstance(key, basestring):
                raise botslib.PluginError(
                    _(u'key of dict is not a string: "%s". Nothing is written.'
                      ) % (plug))
        if 'plugintype' not in plug:
            raise botslib.PluginError(
                _(u'"plugintype" missing in: "%s". Nothing is written.') %
                (plug))

    #special case: compatibility with bots 1.* plugins.
    #in bots 1.*, partnergroup was in separate tabel; in bots 2.* partnergroup is in partner
    #later on, partnergroup will get filtered
    for plug in orgpluglist[:]:
        if plug['plugintype'] == 'partnergroup':
            for plugpartner in orgpluglist:
                if plugpartner['plugintype'] == 'partner' and plugpartner[
                        'idpartner'] == plug['idpartner']:
                    if 'group' in plugpartner:
                        plugpartner['group'].append(plug['idpartnergroup'])
                    else:
                        plugpartner['group'] = [plug['idpartnergroup']]
                    break

    #copy & filter orgpluglist; do plugtype specific adaptions
    pluglist = []
    for plug in orgpluglist:
        if plug['plugintype'] == 'ccode':  #add ccodetrigger. #20101223: this is NOT needed; codetrigger shoudl be in plugin.
            for seachccodetriggerplug in pluglist:
                if seachccodetriggerplug[
                        'plugintype'] == 'ccodetrigger' and seachccodetriggerplug[
                            'ccodeid'] == plug['ccodeid']:
                    break
            else:
                pluglist.append({
                    'plugintype': 'ccodetrigger',
                    'ccodeid': plug['ccodeid']
                })
        elif plug[
                'plugintype'] == 'translate':  #make some fields None instead of '' (translate formpartner, topartner)
            if not plug['frompartner']:
                plug['frompartner'] = None
            if not plug['topartner']:
                plug['topartner'] = None
        elif plug['plugintype'] in [
                'ta', 'filereport'
        ]:  #sqlite can have errortexts that are to long. Chop these
            plug['errortext'] = plug['errortext'][:2047]
        elif plug['plugintype'] == 'routes':
            plug['active'] = False
            if not 'defer' in plug:
                plug['defer'] = False
            else:
                if plug['defer'] is None:
                    plug['defer'] = False
        elif plug['plugintype'] == 'confirmrule':
            plug.pop('id', None)  #id is an artificial key, delete,
        elif plug[
                'plugintype'] not in PLUGINCOMPARELIST:  #if not in PLUGINCOMPARELIST: do not use
            continue
        pluglist.append(plug)
    #sort pluglist: this is needed for relationships
    pluglist.sort(cmp=pluglistcmp, key=operator.itemgetter('plugintype'))
    #2nd sort: sort partenergroups before partners
    pluglist.sort(cmp=pluglistcmpisgroup)
    #~ for plug in pluglist:
    #~ print 'list:',plug

    for plug in pluglist:
        botsglobal.logger.info(u'    Start write to database for: "%s".' %
                               plug)
        #remember the plugintype
        plugintype = plug['plugintype']
        #~ print '\nstart plug', plug
        table = django.db.models.get_model('bots', plug['plugintype'])
        #~ print table

        #delete fields not in model (create compatibility plugin-version)
        loopdictionary = plug.keys()
        for key in loopdictionary:
            try:
                table._meta.get_field(key)
            except django.db.models.fields.FieldDoesNotExist:
                del plug[key]

        #get key(s), put in dict 'sleutel'
        pk = table._meta.pk.name
        if pk == 'id':
            sleutel = {}
            if table._meta.unique_together:
                for key in table._meta.unique_together[0]:
                    sleutel[key] = plug.pop(key)
        else:
            sleutel = {pk: plug.pop(pk)}

        #now we have:
        #- sleutel: unique key fields. mind: translate and confirmrule have empty 'sleutel' now
        #- plug: rest of database fields
        sleutelorg = sleutel.copy(
        )  #make a copy of the original sleutel; this is needed later

        #get real column names for fields in plug
        loopdictionary = plug.keys()
        for fieldname in loopdictionary:
            fieldobject = table._meta.get_field_by_name(fieldname)[0]
            try:
                if fieldobject.column != fieldname:  #if name in plug is not the real field name (in database)
                    plug[fieldobject.column] = plug[
                        fieldname]  #add new key in plug
                    del plug[fieldname]  #delete old key in plug
                    #~ print 'replace _id for:',fieldname
            except:
                print 'no field column for:', fieldname  #should this be raised?

        #get real column names for fields in sleutel; basically the same loop but now for sleutel
        loopdictionary = sleutel.keys()
        for fieldname in loopdictionary:
            fieldobject = table._meta.get_field_by_name(fieldname)[0]
            try:
                if fieldobject.column != fieldname:
                    sleutel[fieldobject.column] = sleutel[fieldname]
                    del sleutel[fieldname]
            except:
                print 'no field column for', fieldname
        #now we have:
        #- sleutel: unique key fields. mind: translate and confirmrule have empty 'sleutel' now
        #- sleutelorg: original key fields
        #- plug: rest of database fields
        #- plugintype
        #all fields have the right database name

        #~ print 'plug attr',plug
        #~ print 'orgsleutel',sleutelorg
        #~ print 'sleutel',sleutel

        #existing ccodetriggers are not overwritten (as deleting ccodetrigger also deletes ccodes)
        if plugintype == 'ccodetrigger':
            listexistingentries = table.objects.filter(**sleutelorg).all()
            if listexistingentries:
                continue
        #now find the entry using the keys in sleutelorg; delete the existing entry.
        elif sleutelorg:  #not for translate and confirmrule; these have an have an empty 'sleutel'
            listexistingentries = table.objects.filter(**sleutelorg).all()
        elif plugintype == 'translate':  #for translate: delete existing entry
            listexistingentries = table.objects.filter(
                fromeditype=plug['fromeditype'],
                frommessagetype=plug['frommessagetype'],
                alt=plug['alt'],
                frompartner=plug['frompartner_id'],
                topartner=plug['topartner_id']).all()
        elif plugintype == 'confirmrule':  #for confirmrule: delete existing entry; but how to find this??? what are keys???
            listexistingentries = table.objects.filter(
                confirmtype=plug['confirmtype'],
                ruletype=plug['ruletype'],
                negativerule=plug['negativerule'],
                idroute=plug.get('idroute'),
                idchannel=plug.get('idchannel_id'),
                editype=plug.get('editype'),
                messagetype=plug.get('messagetype'),
                frompartner=plug.get('frompartner_id'),
                topartner=plug.get('topartner_id')).all()

        if listexistingentries:
            for entry in listexistingentries:
                entry.delete()
            botsglobal.logger.info(
                _(u'        Existing entry in database is deleted.'))

        dbobject = table(**sleutel)  #create db-object
        if plugintype == 'partner':  #for partners, first the partner needs to be saved before groups can be made
            dbobject.save()
        for key, value in plug.items():
            setattr(dbobject, key, value)
        dbobject.save()
        botsglobal.logger.info(_(u'        Write to database is OK.'))
예제 #5
0
def read_plugin(pathzipfile):
    ''' process uploaded plugin. '''
    #test if valid zipfile
    if not zipfile.is_zipfile(pathzipfile):
        raise botslib.PluginError(_(u'Plugin is not a valid file.'))

    #read index file
    try:
        myzipimport = zipimport.zipimporter(pathzipfile)
        importedbotsindex = myzipimport.load_module('botsindex')
        pluglist = importedbotsindex.plugins[:]
        if 'botsindex' in sys.modules:
            del sys.modules['botsindex']
    except:
        txt = botslib.txtexc()
        raise botslib.PluginError(_(u'Error in plugin. Nothing is written. Error:\n%(txt)s'),{'txt':txt})
    else:
        botsglobal.logger.info(_(u'Plugin is OK.'))
        botsglobal.logger.info(_(u'Start writing to database.'))

    #write content of index file to the bots database
    try:
        read_index2database(pluglist)
    except:
        txt = botslib.txtexc()
        raise botslib.PluginError(_(u'Error writing plugin to database. Nothing is written. Error:\n%(txt)s'),{'txt':txt})
    else:
        botsglobal.logger.info(_(u'Writing to database is OK.'))

    #write files to the file system.
    botsglobal.logger.info(_(u'Start writing to files'))
    try:
        warnrenamed = False     #to report in GUI files have been overwritten.
        myzip = zipfile.ZipFile(pathzipfile, mode="r")
        orgtargetpath = botsglobal.ini.get('directories','botspath')
        if (orgtargetpath[-1:] in (os.path.sep, os.path.altsep) and len(os.path.splitdrive(orgtargetpath)[1]) > 1):
            orgtargetpath = orgtargetpath[:-1]
        for zipfileobject in myzip.infolist():
            if zipfileobject.filename not in ['botsindex.py','README','botssys/sqlitedb/botsdb','config/bots.ini'] and os.path.splitext(zipfileobject.filename)[1] not in ['.pyo','.pyc']:
                #~ botsglobal.logger.info(u'Filename in zip "%s".',zipfileobject.filename)
                if zipfileobject.filename[0] == '/':
                    targetpath = zipfileobject.filename[1:]
                else:
                    targetpath = zipfileobject.filename
                #convert for correct environment: repacle botssys, config, usersys in filenames
                if targetpath.startswith('usersys'):
                    targetpath = targetpath.replace('usersys',botsglobal.ini.get('directories','usersysabs'),1)
                elif targetpath.startswith('botssys'):
                    targetpath = targetpath.replace('botssys',botsglobal.ini.get('directories','botssys'),1)
                elif targetpath.startswith('config'):
                    targetpath = targetpath.replace('config',botsglobal.ini.get('directories','config'),1)
                targetpath = botslib.join(orgtargetpath, targetpath)
                #targetpath is OK now.
                botsglobal.logger.info(_(u'    Start writing file: "%(targetpath)s".'),{'targetpath':targetpath})

                if botslib.dirshouldbethere(os.path.dirname(targetpath)):
                    botsglobal.logger.info(_(u'        Create directory "%(directory)s".'),{'directory':os.path.dirname(targetpath)})
                if zipfileobject.filename[-1] == '/':    #check if this is a dir; if so continue
                    continue
                if os.path.isfile(targetpath):  #check if file already exists
                    try:    #this ***sometimes*** fails. (python25, for static/help/home.html...only there...)
                        warnrenamed = True
                    except:
                        pass
                source = myzip.read(zipfileobject.filename)
                target = open(targetpath, "wb")
                target.write(source)
                target.close()
                botsglobal.logger.info(_(u'        File written: "%(targetpath)s".'),{'targetpath':targetpath})
    except:
        txt = botslib.txtexc()
        myzip.close()
        raise botslib.PluginError(_(u'Error writing files to system. Nothing is written to database. Error:\n%(txt)s'),{'txt':txt})
    else:
        myzip.close()
        botsglobal.logger.info(_(u'Writing files to filesystem is OK.'))
        return warnrenamed
예제 #6
0
def read_index2database(orgpluglist):
    #sanity checks on pluglist
    if not orgpluglist:  #list of plugins is empty: is OK. DO nothing
        return
    if not isinstance(orgpluglist,list):   #has to be a list!!
        raise botslib.PluginError(_(u'Plugins should be list of dicts. Nothing is written.'))
    for plug in orgpluglist:
        if not isinstance(plug,dict):
            raise botslib.PluginError(_(u'Plugins should be list of dicts. Nothing is written.'))
        for key in plug.keys():
            if not isinstance(key,basestring):
                raise botslib.PluginError(_(u'Key of dict is not a string: "%(plug)s". Nothing is written.'),{'plug':plug})
        if 'plugintype' not in plug:
            raise botslib.PluginError(_(u'"Plugintype" missing in: "%(plug)s". Nothing is written.'),{'plug':plug})

    #special case: compatibility with bots 1.* plugins.
    #in bots 1.*, partnergroup was in separate tabel; in bots 2.* partnergroup is in partner
    #later on, partnergroup will get filtered
    for plug in orgpluglist[:]:
        if plug['plugintype'] == 'partnergroup':
            for plugpartner in orgpluglist:
                if plugpartner['plugintype'] == 'partner' and plugpartner['idpartner'] == plug['idpartner']:
                    if 'group' in plugpartner:
                        plugpartner['group'].append(plug['idpartnergroup'])
                    else:
                        plugpartner['group'] = [plug['idpartnergroup']]
                    break

    #copy & filter orgpluglist; do plugtype specific adaptions
    pluglist = []
    for plug in orgpluglist:
        if plug['plugintype'] == 'ccode':   #add ccodetrigger. #20101223: this is NOT needed; codetrigger shoudl be in plugin.
            for seachccodetriggerplug in pluglist:
                if seachccodetriggerplug['plugintype'] == 'ccodetrigger' and seachccodetriggerplug['ccodeid'] == plug['ccodeid']:
                    break
            else:
                pluglist.append({'plugintype':'ccodetrigger','ccodeid':plug['ccodeid']})
        elif plug['plugintype'] == 'translate': #make some fields None instead of '' (translate formpartner, topartner)
            if not plug['frompartner']:
                plug['frompartner'] = None
            if not plug['topartner']:
                plug['topartner'] = None
        elif plug['plugintype'] == 'routes':
            plug['active'] = False
            if 'defer' not in plug:
                plug['defer'] = False
            else:
                if plug['defer'] is None:
                    plug['defer'] = False
        elif plug['plugintype'] == 'channel':
            #convert for correct environment: path and mpath in channels
            if 'path' in plug and plug['path'].startswith('botssys'):
                plug['path'] = plug['path'].replace('botssys',botsglobal.ini.get('directories','botssys_org'),1)
            if 'testpath' in plug and plug['testpath'].startswith('botssys'):
                plug['testpath'] = plug['testpath'].replace('botssys',botsglobal.ini.get('directories','botssys_org'),1)
        elif plug['plugintype'] == 'confirmrule':
            plug.pop('id', None)       #id is an artificial key, delete,
        elif plug['plugintype'] not in PLUGINCOMPARELIST:   #if not in PLUGINCOMPARELIST: do not use
            continue
        pluglist.append(plug)
    #sort pluglist: this is needed for relationships
    pluglist.sort(key=lambda plug: plug.get('isgroup',False),reverse=True)       #sort partners on being partnergroup or not
    pluglist.sort(key=lambda plug: PLUGINCOMPARELIST.index(plug['plugintype']))   #sort all plugs on plugintype; are partners/partenrgroups are already sorted, this will still be true in this new sort (python guarantees!)

    for plug in pluglist:
        botsglobal.logger.info(u'    Start write to database for: "%(plug)s".',{'plug':plug})
        #correction for reading partnergroups
        if plug['plugintype'] == 'partner' and plug['isgroup']:
            plug['plugintype'] = 'partnergroep'
        #remember the plugintype
        plugintype = plug['plugintype']
            
        table = django.db.models.get_model('bots',plugintype)

        #delete fields not in model for compatibility; note that 'plugintype' is also removed.
        loopdictionary = plug.keys()
        for key in loopdictionary:
            try:
                table._meta.get_field(key)
            except django.db.models.fields.FieldDoesNotExist:
                del plug[key]

        #get key(s), put in dict 'sleutel'
        pk = table._meta.pk.name
        if pk == 'id':  #'id' is the artificial key django makes, if no key is indicated. Note the django has no 'composite keys'.
            sleutel = {}
            if table._meta.unique_together:
                for key in table._meta.unique_together[0]:
                    sleutel[key] = plug.pop(key)
        else:
            sleutel = {pk:plug.pop(pk)}

        sleutelorg = sleutel.copy()     #make a copy of the original sleutel; this is needed later
        #now we have:
        #- plugintype (is removed from plug)
        #- sleutelorg: original key fields
        #- sleutel: unique key fields. mind: translate and confirmrule have empty 'sleutel'
        #- plug: rest of database fields
        #for sleutel and plug: convert names to real database names

        #get real column names for fields in plug
        loopdictionary = plug.keys()
        for fieldname in loopdictionary:
            fieldobject = table._meta.get_field_by_name(fieldname)[0]
            try:
                if fieldobject.column != fieldname:     #if name in plug is not the real field name (in database)
                    plug[fieldobject.column] = plug[fieldname]  #add new key in plug
                    del plug[fieldname]                         #delete old key in plug
            except:
                raise botslib.PluginError(_(u'No field column for: "%(fieldname)s".'),{'fieldname':fieldname})
        #get real column names for fields in sleutel; basically the same loop but now for sleutel
        loopdictionary = sleutel.keys()
        for fieldname in loopdictionary:
            fieldobject = table._meta.get_field_by_name(fieldname)[0]
            try:
                if fieldobject.column != fieldname:
                    sleutel[fieldobject.column] = sleutel[fieldname]
                    del sleutel[fieldname]
            except:
                raise botslib.PluginError(_(u'No field column for: "%(fieldname)s".'),{'fieldname':fieldname})

        #find existing entry (if exists)
        if sleutelorg:  #note that translate and confirmrule have an empty 'sleutel'
            listexistingentries = table.objects.filter(**sleutelorg)
        elif plugintype == 'translate':
            listexistingentries = table.objects.filter(fromeditype=plug['fromeditype'],
                                                        frommessagetype=plug['frommessagetype'],
                                                        alt=plug['alt'],
                                                        frompartner=plug['frompartner_id'],
                                                        topartner=plug['topartner_id'])
        elif plugintype == 'confirmrule':
            listexistingentries = table.objects.filter(confirmtype=plug['confirmtype'],
                                                        ruletype=plug['ruletype'],
                                                        negativerule=plug['negativerule'],
                                                        idroute=plug.get('idroute'),
                                                        idchannel=plug.get('idchannel_id'),
                                                        messagetype=plug.get('messagetype'),
                                                        frompartner=plug.get('frompartner_id'),
                                                        topartner=plug.get('topartner_id'))
        if listexistingentries:
            dbobject = listexistingentries[0]  #exists, so use existing db-object
        else:
            dbobject = table(**sleutel)         #create db-object
            if plugintype == 'partner':        #for partners, first the partner needs to be saved before groups can be made
                dbobject.save()
        for key,value in plug.iteritems():      #update object with attributes from plugin
            setattr(dbobject,key,value)
        dbobject.save()                     #and save the updated object.
        botsglobal.logger.info(_(u'        Write to database is OK.'))