<commit_before>"use strict"

var
    cfg                = require('config'),
    EmailNotification  = require('email-notification'),
    log4js             = require('log4js')


/*
 * Object variables
 */

var
    gmail,
    log,
    name,
    searches


/**
 * Mailbox model constructor.
 * @param {object}   params - Params to be passed in
 * @param {string}   params.name - Name of the mailbox (for logging and as seen in config item names)
 * @constructor
 */
function Mailbox (params) {

  this.name     = params.name
  this.searches = cfg.mailboxes[this.name].searches

  // logs

  log4js.configure(cfg.log.log4jsConfigs);

  log = log4js.getLogger(cfg.log.appName);
  log.setLevel(cfg.log.level);


  // Log out the searches
  var self = this

  this.searches.forEach( function(el, idx) {
    log.info('[%s] [%s] Search: ', self.name, idx, el)
  })


}


var method = Mailbox.prototype


/**
 * mailbox.getMessages
 *
 * @desc Idetify messages matching search criteria
 *
 * @alias mailbox.getMessages
 *
 * @param  {object} params - Parameters for request (currently unused)
 * @param  {callback} callback - The callback that handles the error response. Returns callback(errMsg)
 * @return {object} errMsg -
 */
method.process = function (params,cb) {

  var mb = this.name

  var self = this;

  self.searches.forEach( function (search, searchIdx) {

    // Retrieve the search and the action to be performed on emails matching that search
    // Default behaviour is to trash messages
    var searchCriteria = search
    var actions = ['trash']
    if (typeof search === 'object') {
      searchCriteria = search.criteria
      actions        = search.actions
    }


    // Create an email-notification object to do all the work
    var tokenFile = cfg.auth.tokenFile.replace("%s",mb);

    var enParams = {
      format:            'metadata',
      gmail: {
        clientSecretFile: cfg.auth.clientSecretFile,
        googleScopes:     cfg.auth.googleScopes,
        name:             cfg.auth.name,
        tokenDir:         cfg.auth.tokenDir,
        tokenFile:        tokenFile
      },
      gmailSearchCriteria: searchCriteria,
      metadataHeaders:    ['subject','date'],
      processedLabelName: cfg.processedLabelName,
      retFields:          ['id','labelIds','payload(headers)']
    }

    if (cfg.maxResults) enParams.maxResults = cfg.maxResults

    var en = new EmailNotification(enParams);



    // Kick off and get the matching messages

    log.info('[%s] [%s] Searching', self.name, searchIdx) ;

    en.getMessages(null, function (err, messages) {
    
      if (err) {
        log.error('[%s] [%s]: Error retrieving emails for search: %s\n%s ', mb, searchIdx, err.message, err.stack)
        cb(err)
        return null;
      }

      var numMessages = (messages)? messages.length : 0
      log.info('[%s] [%s] Found %s messages', self.name, searchIdx, numMessages ) ;

      // Bail if there were no hits
      if (!messages) return;


      // Log out details of matches
      messages.forEach( function(message,idx) {

        // Get metadata for better logging
        var id      = message.id
        var subject = ''
        var date    = ''
        var headers = message.payload.headers

        for (var i = 0; i < headers.length; i++) {
          if      (headers[i].name == "Subject") { subject = headers[i].value }
          else if (headers[i].name == "Date")    { date    = headers[i].value }
        }

        log.info('[%s] [%s] [%s]: Found message: "%s" (%s)', mb, searchIdx, id, subject, date) ;

      })


      //
      // Perform processing actions
      //


      // Update labels
      if (actions.indexOf('applyProcessedLabel') >= 0 || actions.indexOf('markAsRead') >= 0) {

        var applyProcessedLabel = (actions.indexOf('applyProcessedLabel') >= 0)? true : false
        var markAsRead          = (actions.indexOf('markAsRead')          >= 0)? true : false

        log.info('[%s] [%s] Updating %s messages [%s %s]', mb, searchIdx, numMessages, (applyProcessedLabel)? "applyProcessedLabel" : "", (markAsRead)? "markAsRead" : "") ;

        // Do the update
        en.updateLabels({
          applyProcessedLabel: applyProcessedLabel,
          markAsRead:          markAsRead
        }, function (err,resps) {
          if (err) {
            log.error('[%s] [%s] [%s]: Error updating labels: %s\n%s ', mb, searchIdx, resps, err.message, err.stack)
            cb(err)
            return null;
          }
          log.info('[%s] [%s] Updated %s messages', mb, searchIdx, numMessages) ;
        });

      }

      // Trash messages
      if (actions.indexOf('trash') >= 0) {
        en.trash(null, function (err,resps) {
          if (err) {
            log.error('[%s] [%s] [%s]: Error trashing message: %s\n%s ', mb, searchIdx, resps, err.message, err.stack)
            cb(err)
            return null;
          }
          log.info('[%s] [%s] Trashed %s messages', mb, searchIdx, numMessages) ;
        });
      }
    })<commit_msg>Condense trashing to make it part of the updateLabels call. Therefore all updates go through one call instead of two.<commit_after>"use strict"

var
    cfg                = require('config'),
    EmailNotification  = require('email-notification'),
    log4js             = require('log4js')


/*
 * Object variables
 */

var
    gmail,
    log,
    name,
    searches


/**
 * Mailbox model constructor.
 * @param {object}   params - Params to be passed in
 * @param {string}   params.name - Name of the mailbox (for logging and as seen in config item names)
 * @constructor
 */
function Mailbox (params) {

  this.name     = params.name
  this.searches = cfg.mailboxes[this.name].searches

  // logs

  log4js.configure(cfg.log.log4jsConfigs);

  log = log4js.getLogger(cfg.log.appName);
  log.setLevel(cfg.log.level);


  // Log out the searches
  var self = this

  this.searches.forEach( function(el, idx) {
    log.info('[%s] [%s] Search: ', self.name, idx, el)
  })


}


var method = Mailbox.prototype


/**
 * mailbox.getMessages
 *
 * @desc Idetify messages matching search criteria
 *
 * @alias mailbox.getMessages
 *
 * @param  {object} params - Parameters for request (currently unused)
 * @param  {callback} callback - The callback that handles the error response. Returns callback(errMsg)
 * @return {object} errMsg -
 */
method.process = function (params,cb) {

  var mb = this.name

  var self = this;

  self.searches.forEach( function (search, searchIdx) {

    // Retrieve the search and the action to be performed on emails matching that search
    // Default behaviour is to trash messages
    var searchCriteria = search
    var actions = ['trash']
    if (typeof search === 'object') {
      searchCriteria = search.criteria
      actions        = search.actions
    }


    // Create an email-notification object to do all the work
    var tokenFile = cfg.auth.tokenFile.replace("%s",mb);

    var enParams = {
      format:            'metadata',
      gmail: {
        clientSecretFile: cfg.auth.clientSecretFile,
        googleScopes:     cfg.auth.googleScopes,
        name:             cfg.auth.name,
        tokenDir:         cfg.auth.tokenDir,
        tokenFile:        tokenFile
      },
      gmailSearchCriteria: searchCriteria,
      metadataHeaders:    ['subject','date'],
      processedLabelName: cfg.processedLabelName,
      retFields:          ['id','labelIds','payload(headers)']
    }

    if (cfg.maxResults) enParams.maxResults = cfg.maxResults

    var en = new EmailNotification(enParams);



    // Kick off and get the matching messages

    log.info('[%s] [%s] Searching', self.name, searchIdx) ;

    en.getMessages(null, function (err, messages) {
    
      if (err) {
        log.error('[%s] [%s]: Error retrieving emails for search: %s\n%s ', mb, searchIdx, err.message, err.stack)
        cb(err)
        return null;
      }

      var numMessages = (messages)? messages.length : 0
      log.info('[%s] [%s] Found %s messages', self.name, searchIdx, numMessages ) ;

      // Bail if there were no hits
      if (!messages) return;


      // Log out details of matches
      messages.forEach( function(message,idx) {

        // Get metadata for better logging
        var id      = message.id
        var subject = ''
        var date    = ''
        var headers = message.payload.headers

        for (var i = 0; i < headers.length; i++) {
          if      (headers[i].name == "Subject") { subject = headers[i].value }
          else if (headers[i].name == "Date")    { date    = headers[i].value }
        }

        log.info('[%s] [%s] [%s]: Found message: "%s" (%s)', mb, searchIdx, id, subject, date) ;

      })


      //
      // Perform processing actions
      //


      var applyProcessedLabel = (actions.indexOf('applyProcessedLabel') >= 0)? true : false
      var markAsRead          = (actions.indexOf('markAsRead')          >= 0)? true : false
      var trash               = (actions.indexOf('trash')               >= 0)? true : false

      log.info('[%s] [%s] Updating %s messages [%s %s %s]', mb, searchIdx, numMessages, (applyProcessedLabel)? "applyProcessedLabel" : "", (markAsRead)? "markAsRead" : "", (trash)? "trash" : "") ;

      // Do the update
      en.updateLabels({
        applyProcessedLabel: applyProcessedLabel,
        markAsRead:          markAsRead,
        trash:               trash
      }, function (err,resps) {
        if (err) {
          log.error('[%s] [%s] [%s]: Error updating labels: %s\n%s ', mb, searchIdx, resps, err.message, err.stack)
          cb(err)
          return null;
        }
        log.info('[%s] [%s] Updated %s messages', mb, searchIdx, numMessages) ;
      });
    })
{'fraction_non_alphanumeric': 0.13222119246215633, 'fraction_numerical': 0.0022654721449902175, 'mean_word_length': 2.2799729821006416, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1146956', 'n_tokens_mistral': 2995, 'n_tokens_neox': 2887, 'n_words': 806}