var _ = require('underscore'), databank = require('databank'), async = require('async'); var api = function(dbot) { var api = { 'getDrugCategory': function(name, callback) { name = name.toLowerCase(); this.db.read('drug_categories', name, function(err, cat) { callback(cat); }); }, 'getIRCFormattedDrug': function(name, property, callback) { this.api.getDrug(name, function(drug) { if(drug && !_.has(drug, 'err')) { if(_.has(drug, 'links') && _.has(drug.links, 'experiences')) { drug.properties.experiences = drug.links.experiences; } if(!_.isUndefined(property)) { if(_.has(drug.properties, property)) { var info = drug.properties[property]; // TODO: Remove magic vars and move to formatProperty API func if(property == 'dose') { info = info.replace(/Threshold:/gi, "\u00032Threshold\u000f:"); info = info.replace(/Light:/gi, "\u00033Light\u000f:"); info = info.replace(/Common:/gi, "\u00037Common\u000f:"); info = info.replace(/Strong:/gi, "\u00035Strong\u000f:"); info = info.replace(/Heavy:/gi, "\u00034Heavy\u000f:"); } if(property == 'aliases') info = info.join(', '); callback(name + ' ' + property + ': ' + info); } else { callback(name + ' Info: ' + _.keys(drug.properties).join(', ') + ' - http://drugs.tripsit.me/' + drug.name); } } else { callback(name + ' Info: ' + _.keys(drug.properties).join(', ') + ' - http://drugs.tripsit.me/' + drug.name); } } else { callback(null); } }); }, 'getInteraction': function(drugAName, drugBName, callback) { drugAName = drugAName.toLowerCase(); drugBName = drugBName.toLowerCase(); if(drugAName == 'ssri' || drugAName == 'snri' || drugAName == 'snris') { drugAName = 'ssris'; } else if(drugAName == 'maoi') { drugAName = 'maois'; } if(drugBName == 'ssri' || drugBName == 'snri' || drugBName == 'snris') { drugBName = 'ssris'; } else if(drugBName == 'maoi') { drugBName = 'maois'; } this.api.getDrug(drugAName, function(drugA) { if(!_.has(drugA, 'err') || _.has(this.combos, drugAName)) { this.api.getDrug(drugBName, function(drugB) { if(!_.has(drugB, 'err') || _.has(this.combos, drugBName)) { var safetyCategoryA = null, safetyCategoryB = null; if(_.has(this.combos, drugAName)) { safetyCategoryA = drugAName; } else if(_.has(this.combos, drugA.name)) { safetyCategoryA = drugA.name; } else if(drugA.name.match(/^do.$/i)) { safetyCategoryA = 'dox'; } else if(drugA.name.match(/^2c-.$/i)) { safetyCategoryA = '2c-x'; } else if(drugA.name.match(/^25.-nbome/i)) { safetyCategoryA = 'nbomes'; } else if(drugA.name.match(/^5-meo-..t$/i)) { safetyCategoryA = '5-meo-xxt'; } else if(_.include(drugA.categories, 'benzodiazepine')) { safetyCategoryA = 'benzodiazepines'; } else if(_.include(drugA.categories, 'opioid')) { safetyCategoryA = 'opioids'; } else if(_.include(drugB.categories, 'benzo')) { safetyCategoryB = 'benzos'; } else if(_.include(drugA.categories, 'stimulant')) { safetyCategoryA = 'amphetamines'; } else if(drugA.name == 'ghb' || drugA.name == 'gbl') { safetyCategoryA = 'ghb/gbl'; } if(_.has(this.combos, drugBName)) { safetyCategoryB = drugBName; } else if(_.has(this.combos, drugB.name)) { safetyCategoryB = drugB.name; } else if(drugB.name.match(/^do.$/i)) { safetyCategoryB = 'dox'; } else if(drugB.name.match(/^2c-.$/i)) { safetyCategoryB = '2c-x'; } else if(drugB.name.match(/^25.-nbome/i)) { safetyCategoryB = 'nbomes'; } else if(drugB.name.match(/^5-meo-..t$/i)) { safetyCategoryB = '5-meo-xxt'; } else if(_.include(drugB.categories, 'benzodiazepine')) { safetyCategoryB = 'benzodiazepines'; } else if(_.include(drugB.categories, 'opioid')) { safetyCategoryB = 'opioids'; } else if(_.include(drugB.categories, 'benzo')) { safetyCategoryB = 'benzos'; } else if(_.include(drugB.categories, 'stimulant')) { safetyCategoryB = 'amphetamines'; } else if(drugB.name == 'ghb' || drugB.name == 'gbl') { safetyCategoryB = 'ghb/gbl'; } if(safetyCategoryA && safetyCategoryB) { if(safetyCategoryA != safetyCategoryB) { var result = _.clone(this.combos[safetyCategoryA][safetyCategoryB]); result['interactionCategoryA'] = safetyCategoryA; result['interactionCategoryB'] = safetyCategoryB; return callback(result); } else { if(safetyCategoryA == 'benzodiazepines') { return callback({'err': true, 'code': 'ssb', 'msg': 'Drug A and B are the same safety category.'}); } else { return callback({'err': true, 'code': 'ssc', 'msg': 'Drug A and B are the same safety category.'}); } } } else { return callback(false); } } else { return callback({'err': true, 'msg': 'Drug B not found.'}); } }.bind(this)); } else { return callback({'err': true, 'msg': 'Drug A not found.'}); } }.bind(this)); }, 'getDrug': function(name, callback) { name = name.toLowerCase(); this.db.read('drugs', name, function(err, drug) { if(!drug) { this.db.scan('drugs', function(dMatch) { if(_.include(dMatch.aliases, name)) { drug = dMatch; if(!_.isUndefined(drug.aliases)) drug.properties.aliases = drug.aliases; } }, function() { if(drug) { if(!_.isUndefined(drug.aliases)) drug.properties.aliases = drug.aliases; if(!_.isUndefined(drug.categories)) drug.properties.categories = drug.categories; if(_.has(dbot.modules.tripsit.combos, drug.name)) { drug.combos = dbot.modules.tripsit.combos[drug.name]; } if(_.has(drug.properties, 'dose')) { var doses = drug.properties.dose.split('|'); var regex = /(([\w-]+):\s([\/\.\w\d-\+µ]+))/ig; drug.formatted_dose = {}; if(doses.length > 1 || !doses[0].split(' ')[0].match(':')) { _.each(doses, function(dString) { dString = dString.replace(/\s\s+/g, ' '); var roa = dString.trim().split(' ')[0]; var match = regex.exec(dString); if(roa.match(/note/i)) { drug.dose_note = dString; } else { drug.formatted_dose[roa] = {}; while(match != null) { drug.formatted_dose[roa][match[2]] = match[3]; match = regex.exec(dString); } } }); } else { var roa = 'Oral'; var match = regex.exec(doses[0]); if(roa.match(/note/i)) { drug.dose_note = doses[0]; } else { drug.formatted_dose[roa] = {}; while(match != null) { drug.formatted_dose[roa][match[2]] = match[3]; match = regex.exec(doses[0]); } } } } if(_.has(drug.properties, 'effects')) { drug.formatted_effects = _.collect(drug.properties.effects.split(/[\.,]+/), function(item) { return item.trim(); }); } if(_.has(drug.properties, 'duration')) { var roas = drug.properties.duration.split('|'); drug.formatted_duration = {}; if(roas.length > 1 || roas[0].match(':')) { _.each(roas, function(roa) { if(roa.toLowerCase().match('note')) { return; } var match = roa.match(/([\w-\/]+):?\s([\.\w\d-\+]+)/i); if(match) { drug.formatted_duration[match[1]] = match[2]; } }); } else { var match = drug.properties['duration'].match(/([\.\w\d-\+]+)/i); drug.formatted_duration = {'value':match[1]}; } if(drug.properties.duration.indexOf('minutes') != -1) { drug.formatted_duration._unit = 'minutes'; } if(drug.properties.duration.indexOf('hours') != -1) { drug.formatted_duration._unit = 'hours'; } } if(_.has(drug.properties, 'onset')) { var roas = drug.properties.onset.split('|'); drug.formatted_onset = {}; if(roas.length > 1 || roas[0].match(':')) { _.each(roas, function(roa) { if(roa.toLowerCase().match('note')) { return; } var match = roa.match(/([\w-\/]+):?\s([\.\w\d-\+]+)/i); if(match) { drug.formatted_onset[match[1]] = match[2]; } }); } else { var match = drug.properties['onset'].match(/([\.\w\d-\+]+)/i); drug.formatted_onset = {'value':match[1]}; } if(drug.properties.onset.indexOf('minutes') != -1) { drug.formatted_onset._unit = 'minutes'; } if(drug.properties.onset.indexOf('hours') != -1) { drug.formatted_onset._unit = 'hours'; } } if(_.has(drug.properties, 'after-effects')) { var roas = drug.properties['after-effects'].split('|'); drug.formatted_aftereffects = {}; if(roas.length > 1 || roas[0].match(':')) { _.each(roas, function(roa) { if(roa.toLowerCase().match('note')) { return; } var match = roa.match(/([\w\/]+):?\s([\.\w\d-\+]+)/i); if(match) { drug.formatted_aftereffects[match[1]] = match[2]; } }); } else { var match = drug.properties['after-effects'].match(/([\.\w\d-\+]+)/i); drug.formatted_aftereffects = {'value':match[1]}; } if(drug.properties['after-effects'].indexOf('minutes') != -1) { drug.formatted_aftereffects._unit = 'minutes'; } if(drug.properties['after-effects'].indexOf('hours') != -1) { drug.formatted_aftereffects._unit = 'hours'; } } if(!_.has(drug, 'pretty_name')) { drug.pretty_name = drug.name; if(drug.name.length <= 4 || drug.name.indexOf('-') != -1) { drug.pretty_name = drug.name.toUpperCase(); } else { drug.pretty_name = drug.name.charAt(0).toUpperCase() + drug.name.slice(1); } drug.pretty_name = drug.pretty_name.replace(/MEO/, 'MeO'); drug.pretty_name = drug.pretty_name.replace(/ACO/, 'AcO'); drug.pretty_name = drug.pretty_name.replace(/NBOME/, 'NBOMe'); drug.pretty_name = drug.pretty_name.replace(/MIPT/, 'MiPT'); drug.pretty_name = drug.pretty_name.replace(/DIPT/, 'DiPT'); } } if(drug) { callback(drug); } else { callback({'err': true, 'msg': 'No drug found.'}); } }); } else { if(drug) { if(!_.isUndefined(drug.aliases)) drug.properties.aliases = drug.aliases; if(!_.isUndefined(drug.categories)) drug.properties.categories = drug.categories; if(_.has(dbot.modules.tripsit.combos, drug.name)) { drug.combos = dbot.modules.tripsit.combos[drug.name]; } if(_.has(drug.properties, 'dose')) { var doses = drug.properties.dose.split('|'); var regex = /(([\w-]+):\s([\/\.\w\d-\+µ]+))/ig; drug.formatted_dose = {}; if(doses.length > 1 || !doses[0].split(' ')[0].match(':')) { _.each(doses, function(dString) { dString = dString.replace(/\s\s+/g, ' '); var roa = dString.trim().split(' ')[0]; var match = regex.exec(dString); if(roa.match(/note/i)) { drug.dose_note = dString; } else { drug.formatted_dose[roa] = {}; while(match != null) { drug.formatted_dose[roa][match[2]] = match[3]; match = regex.exec(dString); } } }); } else { var roa = 'Oral'; var match = regex.exec(doses[0]); if(roa.match(/note/i)) { drug.dose_note = doses[0]; } else { drug.formatted_dose[roa] = {}; while(match != null) { drug.formatted_dose[roa][match[2]] = match[3]; match = regex.exec(doses[0]); } } } } if(_.has(drug.properties, 'effects')) { drug.formatted_effects = _.collect(drug.properties.effects.split(/[\.,]+/), function(item) { return item.trim(); }); } if(_.has(drug.properties, 'duration')) { var roas = drug.properties.duration.split('|'); drug.formatted_duration = {}; if(roas.length > 1 || roas[0].match(':')) { _.each(roas, function(roa) { if(roa.toLowerCase().match('note')) { return; } var match = roa.match(/([\w-\/]+):?\s([\.\w\d-\+]+)/i); if(match) { drug.formatted_duration[match[1]] = match[2]; } }); } else { var match = drug.properties['duration'].match(/([\.\w\d-\+]+)/i); drug.formatted_duration = {'value':match[1]}; } if(drug.properties.duration.indexOf('minutes') != -1) { drug.formatted_duration._unit = 'minutes'; } if(drug.properties.duration.indexOf('hours') != -1) { drug.formatted_duration._unit = 'hours'; } } if(_.has(drug.properties, 'onset')) { var roas = drug.properties.onset.split('|'); drug.formatted_onset = {}; if(roas.length > 1 || roas[0].match(':')) { _.each(roas, function(roa) { if(roa.toLowerCase().match('note')) { return; } var match = roa.match(/([\/\w-]+):??\s([\.\w\d-\+]+)/i); if(match) { drug.formatted_onset[match[1]] = match[2]; } }); } else { var match = drug.properties['onset'].match(/([\.\w\d-\+]+)/i); drug.formatted_onset = {'value':match[1]}; } if(drug.properties.onset.indexOf('minutes') != -1) { drug.formatted_onset._unit = 'minutes'; } if(drug.properties.onset.indexOf('hours') != -1) { drug.formatted_onset._unit = 'hours'; } } if(_.has(drug.properties, 'after-effects')) { var roas = drug.properties['after-effects'].split('|'); drug.formatted_aftereffects = {}; if(roas.length > 1 || roas[0].match(':')) { _.each(roas, function(roa) { if(roa.toLowerCase().match('note')) { return; } var match = roa.match(/([\w\/]+):?\s([\.\w\d-\+]+)/i); if(match) { drug.formatted_aftereffects[match[1]] = match[2]; } }); } else { var match = drug.properties['after-effects'].match(/([\.\w\d-\+]+)/i); drug.formatted_aftereffects = {'value':match[1]}; } if(drug.properties['after-effects'].indexOf('minutes') != -1) { drug.formatted_aftereffects._unit = 'minutes'; } if(drug.properties['after-effects'].indexOf('hours') != -1) { drug.formatted_aftereffects._unit = 'hours'; } } if(!_.has(drug, 'pretty_name')) { drug.pretty_name = drug.name; if(drug.name.length <= 4 || drug.name.indexOf('-') != -1) { drug.pretty_name = drug.name.toUpperCase(); } else { drug.pretty_name = drug.name.charAt(0).toUpperCase() + drug.name.slice(1); } drug.pretty_name = drug.pretty_name.replace(/MEO/, 'MeO'); drug.pretty_name = drug.pretty_name.replace(/ACO/, 'AcO'); drug.pretty_name = drug.pretty_name.replace(/NBOME/, 'NBOMe'); drug.pretty_name = drug.pretty_name.replace(/MIPT/, 'MiPT'); drug.pretty_name = drug.pretty_name.replace(/DIPT/, 'DiPT'); } } if(drug) { callback(drug); } else { callback({'err': true, 'msg': 'No drug found.'}); } } }.bind(this)); }, 'getAllDrugNames': function(callback) { var names = []; this.db.scan('drugs', function(drug) { if(drug) { names.push(drug.name); } }, function() { callback(names); }); }, 'getAllDrugNamesByCategory': function(category, callback) { this.api.getAllDrugs(function(names) { callback(_.pluck(_.filter(names, function(a) { return _.include(a.categories, category); }), 'name')); }); }, 'getAllDrugs': function(callback) { this.api.getAllDrugNames(function(names) { var drugs = {}; async.each(names, function(name, done) { if(!_.isUndefined(name)) { this.api.getDrug(name, function(drug) { drugs[name] = drug; done(); }); } else { done(); } }.bind(this), function() { callback(drugs); }); }.bind(this)); }, 'getAllCategories': function(callback) { var categories = {}; this.db.scan('drug_categories', function(cat) { categories[cat.name] = cat; }, function() { callback(categories); }); }, 'getAllDrugAliases': function(callback) { this.api.getAllDrugNames(function(names) { var fullNames = []; async.each(names, function(name, done) { if(!_.isUndefined(name)) { this.api.getDrug(name, function(drug) { fullNames.push(name); fullNames = _.union(fullNames, drug.aliases); done(); }); } else { done(); } }.bind(this), function() { callback(fullNames); }); }.bind(this)); }, 'delDrug': function(name, callback) { this.db.del('drugs', name.toLowerCase(), function() { callback(); }); }, 'setDrugProperty': function(drug, property, content, callback) { drug.properties[property] = content; this.db.save('drugs', drug.name, drug, callback); }, 'setCategoryProperty': function(category, property, content, callback) { category[property] = content; this.db.save('drug_categories', category.name, category, callback); }, 'delDrugProperty': function(drug, property, callback) { delete drug.properties[property]; this.db.save('drugs', drug.name, drug, callback); }, 'createDrug': function(name, callback) { name = name.toLowerCase(); this.db.create('drugs', name, { 'name': name, 'properties': {} }, callback); } }; api['getDrug'].external = true; api['getDrug'].extMap = [ 'name', 'callback' ]; api['getAllDrugNames'].external = true; api['getAllDrugNames'].extMap = [ 'callback' ]; api['getAllDrugNamesByCategory'].external = true; api['getAllDrugNamesByCategory'].extMap = [ 'category', 'callback' ]; api['getAllDrugAliases'].external = true; api['getAllDrugAliases'].extMap = [ 'callback' ]; api['getAllDrugs'].external = true; api['getAllDrugs'].extMap = [ 'callback' ]; api['getAllCategories'].external = true; api['getAllCategories'].extMap = [ 'callback' ]; api['getInteraction'].external = true; api['getInteraction'].extMap = [ 'drugA', 'drugB', 'callback' ]; return api; }; exports.fetch = function(dbot) { return api(dbot); };