<commit_before>//
// Database module
//

'use strict';


if (process.env.NODE_ENV !== 'production') {
  // Load the .env file, that sets process.env.
  require('dotenv').load();
}

const pg = require('pg');
const db = new pg.Client({
  ssl: true,
  connectionString: process.env.DATABASE_URL
});
db.connect(err => {
  if (err) throw err;
});

// Integrate with airtable
const base = require('airtable').base(process.env.AIRTABLE_BASE);

const removeUserByFbid = (fbid, callback) => {
  findOrCreateUser(fbid, user => {
    base('Users').destroy(user.id, function(err, deletedRecord) {
      if (err) { console.error(err); }
      console.log('Deleted record', deletedRecord.id);
      callback('Deleted record ' + fbid);
    });
  });
};

const findOrCreateUser = (fbid, callback) => {
  console.log('Finding user with fbid ' + fbid);

  base('Users').select({
    filterByFormula: '({fbid} = "' + fbid + '")'
  }).eachPage(function page(records, fetchNextPage) {
    if (records !== undefined && records[0] !== undefined) {
      const userData = records[0].fields;
      userData.id = records[0].getId();
      callback(userData);
    } else {
      const userData = {
        fbid,
        modality: '',
        seenBefore: false,
        reminderTime: '',
        habit: '',
        habitCategory: '',
        snoozesToday: 0,
        streak: 0,
        totalNumberOfSnoozes: 0,
        totalNumberOfFailedSnoozes: 0,
        expectingAge: false,
        age: '',
        hasUsedHabitAppsBefore: false,
        expectingPreviousHabits: false,
        previousHabits: '',
        hasUsedHabitAppsBeforeWorked: false,
        expectingHabitContext: false,
        habitContext: '',
        email: '',
        interview: false,
        expectingContactDetails: false,
        gender: '',
        expectingMoreFeedback: false,
        survey1a: '',
        survey1b: '',
        survey1c: '',
        survey1d: '',
        surveyModality1a: '',
        surveyModality1b: '',
        surveyModality1c: '',
        surveyModality1d: '',
        moreFeedback: '',
        finished: false
      };

      // User doesn't exist, so lets create them
      base('Users').create(userData, (err, record) => {
        if (err) {
          console.error(err);
          throw new Error(err);
        }
        console.log('Created user in database fbid: ' + fbid);
        userData.id = record.getId();
        callback(userData);
      });
    }
  }, function done(err) {
    if (err) {
      console.error(err);
      throw new Error(err);
    }
  });
};

const getUsersByStreak = callback => {
  let users = [];
  base('Users').select({
    sort: [{field: "streak", direction: "desc"}]
  }).eachPage(function page(records, fetchNextPage) {
    for (let i = 0; i < records.length; i++) {
      const usr = records[i].fields;
      usr.index = i;
      users.push(usr);
    }
    console.log('fetching next page')
    fetchNextPage();
  }, function done(err) {
    if (err) {
      console.log(err);
      callback(false);
    } else {
      callback(users);
    }
  });
};

const getGlobals = callback => {
  db.query('select * from globals limit 1', (err, res) => {
    if (err) {
      console.error(err.error);
      callback(err.error);
    } else {
      for (let i = 0, len = res.rows.length; i < len; i++) {
        callback(res.rows[i]);
      }
    }
  });
};

const updateGlobals = (globals, callback) => {
  console.log('Updating globals ' + JSON.stringify(globals));
  const callbackGlobals = globals;
  const id = callbackGlobals.id;
  delete globals.id;
  base('Globals').update(id, globals, (err, record) => {
    if (err) {
      console.error(err);
      throw new Error(err);
    }
    callbackGlobals.id = record.getId();
    callback(callbackGlobals);
  });
};

const hasUserCompletedHabit = (user, callback) => {
  const today = (new Date()).toUTCString().slice(5, -13); // Save date;

  base('Habits').select({
    filterByFormula: 'AND({day} = "' + today + '", {fbid} = "' + user.fbid + '")'
  }).eachPage(function page(records, fetchNextPage) {
    if (records !== undefined && records[0] !== undefined) {
      const habitFound = records[0].fields;
      console.log('User has completed their habit today:');
      console.log(habitFound);
      callback(true);
    } else {
      console.log('User has not completed their habit today.')
      callback(false);
    }
  }, function done(err) {
    if (err) {
      console.error(err);
      throw new Error(err);
    }
  });
};


const updateHabit = (habit, callback) => {<commit_msg>Moved update globals to postgres<commit_after>//
// Database module
//

'use strict';

if (process.env.NODE_ENV !== 'production') {
  // Load the .env file, that sets process.env.
  require('dotenv').load();
}

const pg = require('pg');
const db = new pg.Client({
  ssl: true,
  connectionString: process.env.DATABASE_URL
});
db.connect(err => {
  if (err) throw err;
});

// Integrate with airtable
const base = require('airtable').base(process.env.AIRTABLE_BASE);

const removeUserByFbid = (fbid, callback) => {
  findOrCreateUser(fbid, user => {
    base('Users').destroy(user.id, function(err, deletedRecord) {
      if (err) { console.error(err); }
      console.log('Deleted record', deletedRecord.id);
      callback('Deleted record ' + fbid);
    });
  });
};

const findOrCreateUser = (fbid, callback) => {
  console.log('Finding user with fbid ' + fbid);

  base('Users').select({
    filterByFormula: '({fbid} = "' + fbid + '")'
  }).eachPage(function page(records, fetchNextPage) {
    if (records !== undefined && records[0] !== undefined) {
      const userData = records[0].fields;
      userData.id = records[0].getId();
      callback(userData);
    } else {
      const userData = {
        fbid,
        modality: '',
        seenBefore: false,
        reminderTime: '',
        habit: '',
        habitCategory: '',
        snoozesToday: 0,
        streak: 0,
        totalNumberOfSnoozes: 0,
        totalNumberOfFailedSnoozes: 0,
        expectingAge: false,
        age: '',
        hasUsedHabitAppsBefore: false,
        expectingPreviousHabits: false,
        previousHabits: '',
        hasUsedHabitAppsBeforeWorked: false,
        expectingHabitContext: false,
        habitContext: '',
        email: '',
        interview: false,
        expectingContactDetails: false,
        gender: '',
        expectingMoreFeedback: false,
        survey1a: '',
        survey1b: '',
        survey1c: '',
        survey1d: '',
        surveyModality1a: '',
        surveyModality1b: '',
        surveyModality1c: '',
        surveyModality1d: '',
        moreFeedback: '',
        finished: false
      };

      // User doesn't exist, so lets create them
      base('Users').create(userData, (err, record) => {
        if (err) {
          console.error(err);
          throw new Error(err);
        }
        console.log('Created user in database fbid: ' + fbid);
        userData.id = record.getId();
        callback(userData);
      });
    }
  }, function done(err) {
    if (err) {
      console.error(err);
      throw new Error(err);
    }
  });
};

const getUsersByStreak = callback => {
  let users = [];
  base('Users').select({
    sort: [{field: "streak", direction: "desc"}]
  }).eachPage(function page(records, fetchNextPage) {
    for (let i = 0; i < records.length; i++) {
      const usr = records[i].fields;
      usr.index = i;
      users.push(usr);
    }
    console.log('fetching next page')
    fetchNextPage();
  }, function done(err) {
    if (err) {
      console.log(err);
      callback(false);
    } else {
      callback(users);
    }
  });
};

const getGlobals = callback => {
  db.query('select * from globals limit 1', (err, res) => {
    if (err) {
      console.error(err.error);
      callback(err.error);
    } else {
      for (let i = 0, len = res.rows.length; i < len; i++) {
        callback(res.rows[i]);
      }
    }
  });
};

const updateGlobals = (globals, callback) => {
  console.log('Updating globals ' + JSON.stringify(globals));
  db.query('update globals SET "remainingDays"=' + globals.remainingDays + ', "studyActive"=' + globals.studyActive + ' where id=1;', (err, res) => {
    if (err) {
        console.error(err.error);
        callback(err.error);
      } else {
        callback(globals);
      }
  });
};

const hasUserCompletedHabit = (user, callback) => {
  const today = (new Date()).toUTCString().slice(5, -13); // Save date;

  base('Habits').select({
    filterByFormula: 'AND({day} = "' + today + '", {fbid} = "' + user.fbid + '")'
  }).eachPage(function page(records, fetchNextPage) {
    if (records !== undefined && records[0] !== undefined) {
      const habitFound = records[0].fields;
      console.log('User has completed their habit today:');
      console.log(habitFound);
      callback(true);
    } else {
      console.log('User has not completed their habit today.')
      callback(false);
    }
  }, function done(err) {
    if (err) {
      console.error(err);
      throw new Error(err);
    }
  });
};


const updateHabit = (habit, callback) => {
{'fraction_non_alphanumeric': 0.16075156576200417, 'fraction_numerical': 0.005164267662894188, 'mean_word_length': 2.534757281553398, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 27, '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': '317063', 'n_tokens_mistral': 2943, 'n_tokens_neox': 2940, 'n_words': 630}