def __init__(self,config=None,antispam=None,_id=None,parentid=None,localfile=None,handler=None,messagedata=None,dehydrated=None):
        '''Create message'''
        

        if dehydrated: 
            # Recreate from a dict
            # See http://stackoverflow.com/questions/1305532/convert-python-dict-to-object
            self.__dict__.update(dehydrated)     
            return   
        
        # FIXME: combine
        if config is None:
            logging.error('Please provide config when creating new messages')
            return
        if antispam is None:
            logging.error('Please provide antispam info when creating new messages')
            return
        if _id is None:
            logging.error('Please provide _id info when creating new messages')
            return

        
        # Info that's common across all messages
        # Note we store a list as it's JSON serializable. A native datetime object isn't.
        now = datetime.utcnow()
        self.posttime = {
            'year':now.year, 
            'month':now.month, 
            'day':now.day, 
            'hour':now.hour, 
            'minute':now.minute, 
            'second':now.second
        }
        self.prettydate = self.getprettydate()
        
        self._id = _id        
        self.localfile = localfile
        self.preview, self.embedcode, self.headline, self.intro, self.thread, self.availavatars, self.likecount = None, None, None, None, None, None, None
        self.treecount = 0
        self.useralerts, self.comments = [], []
        self.score = 1
        
        if messagedata:
            # Preconfigured data from injector
            self.author = messagedata['author']
            self.posttext = messagedata['posttext']
            self.challenge = messagedata['challenge']
            self.response = messagedata['response']
            self.ip = messagedata['ip']
            self.useragent = messagedata['useragent']
            self.referer = messagedata['referer']
            self.imagedata = messagedata['imagedata']
            self.host = messagedata['host']
            self.article = messagedata['article']
            self.sessionid = '1'
        elif handler:
            # Create message from handler data
            self.author = 'Anonymous'
            self.posttext = handler.get_argument('posttext')
            self.useragent = handler.request.headers['User-Agent']
            # nginx real IP
            if handler.request.headers in 'X-Real-Ip':
                self.ip = handler.request.headers['X-Real-Ip'] 
            else:
                self.ip = handler.request.remote_ip
            self.referer = handler.request.headers['Referer']
            self.host = handler.request.headers['Host']
            # Add capctha info if enabled
            if handler.application.config['captcha'].as_bool('enabled'):
                self.challenge = handler.get_argument('recaptcha_challenge_field')
                self.response = handler.get_argument('recaptcha_response_field')
            else:
                self.challenge,self.response = None, None
            # Add image data if enabled
            if 'image' in handler.request.files:
                self.imagedata = handler.request.files['image']
            else:
                self.imagedata = None
            self.sessionid = handler.getorsetsessionid()

        else:   
            logging.error('No handler specified, and not dehydrated! Cannot create message')        
        
        # Are we an article or a reply
        self.parentid = parentid
        if self.istop():
            # We're a top-level article
            logging.info('Creating new article '+str(self._id))
            # Available avatars for sessions - copy of config.
            self.availavatars = config['posting']['avatars']
            logging.info('DEBUG:'+str(len(self.availavatars))+' created in this article')
            random.shuffle(self.availavatars)
            # Create dict of session / avatar matchings
            self.sessionavatars = {}

            # Thread is myself
            self.thread = self._id
            
            # Grab an avatar from my own list!
            self.sessionavatars[self.sessionid] = self.availavatars.pop()
            logging.info('DEBUG:'+str(len(self.availavatars))+' left in this article')
            
            # Currently only top level messages can have links, pictures or embeds
            # Process embeds (FIXME - must come before saveimages due to check for existing embeds in saveimages)
            self.checklinksandembeds(config)

            # If there's no local image file, save image from web url
            if self.localfile is None:
                self.saveimages(config)

            # Make preview            
            if self.localfile is not None and config['images'].as_bool('enabled'):
                self.makepreviewpic(self.localfile,config['images'])
                logging.info('Made preview picture.')
            else:    
                logging.warn('Not making image as local file not specified or images disabled.')
            logging.info('Preview pic is: '+str(self.preview))
            
        else:
            # We're a reply
            logging.info('Creating new reply '+str(self._id))   

            # Add our new comment ID as a child of parent, increment parents score            
            parent = handler.application.dbconnect.messages.find_one({'_id':int(parentid)})
            if parentid:
                # We're a reply
                parent['comments'].append(_id)

                # Increment parent score for message
                parent['score'] += config['scoring'].as_int('comment')
                
                # Every reply copies its 'thread' from its parent, which points back to the original post 
                self.thread = parent['thread']
                logging.info('Thread is '+str(self.thread))

                # Save parent now
                # Note that 'ancestor' (later) may be the same comment, so we need to save this now.
                logging.info('Adding comment '+str(self._id)+' as child of parent '+str(parentid))
                handler.application.dbconnect.messages.save(parent)

                # Take an avatar from the sessions avatar/dict in ancestor
                ancestor = handler.application.dbconnect.messages.find_one({'_id':int(self.thread)})
                if self.sessionid not in ancestor['sessionavatars']:
                    # This is the first time this sessionid has commented
                    # Grab an available avatar from the ancestor to use for this sessionid
                    myavatar = ancestor['availavatars'].pop()
                    logging.info('DEBUG:'+str(len(ancestor['availavatars']))+' left in the parent')
                    ancestor['sessionavatars'][self.sessionid] = myavatar
                    logging.info('Sessionid '+self.sessionid+' has commented in this thread for the first time. Assigned '+myavatar+' for message '+str(self._id))
                    ancestor['treecount'] += 1
                    handler.application.dbconnect.messages.save(ancestor)
                    # Here ancestor is saved to db with correct info, but it gets overridden later                    
                else: 
                    logging.info('This sessionid '+self.sessionid+' has commented in this thread before, using existing avatar '+ancestor['sessionavatars'][self.sessionid])        
                                
            else:    
                logging.warn('Error! Could not find parent with parentid '+str(parentid)+' in DB')
                
        
        
        # Validate the users input    
        #self.getimagetext(self.localfile,config['images'])
        self.checktext(config)
        self.checkcaptcha(config)
        self.checkspam(config,antispam)
        self.checkporn(config)
        self.makeintro(config['posting'])
        
        # Override existing links
        self.link = '/discuss/'+str(self._id)
dataset/ETHPy150Open mikemaccana/imeveryone/usermessages.py/Message.__init__/swapped operands of `in`