parent
29947611f6
commit
67e2ff987f
|
@ -10,11 +10,13 @@ const paths = require('path');
|
||||||
const async = require('async');
|
const async = require('async');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
|
const moment = require('moment');
|
||||||
|
|
||||||
// database handles
|
// database handles
|
||||||
let dbs = {};
|
let dbs = {};
|
||||||
|
|
||||||
exports.getModDatabasePath = getModDatabasePath;
|
exports.getModDatabasePath = getModDatabasePath;
|
||||||
|
exports.getISOTimestampString = getISOTimestampString;
|
||||||
exports.initializeDatabases = initializeDatabases;
|
exports.initializeDatabases = initializeDatabases;
|
||||||
|
|
||||||
exports.dbs = dbs;
|
exports.dbs = dbs;
|
||||||
|
@ -46,6 +48,11 @@ function getModDatabasePath(moduleInfo, suffix) {
|
||||||
return paths.join(conf.config.paths.modsDb, `${full}.sqlite3`);
|
return paths.join(conf.config.paths.modsDb, `${full}.sqlite3`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getISOTimestampString(ts) {
|
||||||
|
ts = ts || moment();
|
||||||
|
return ts.format('YYYY-MM-DDTHH:mm:ss.SSSZ');
|
||||||
|
}
|
||||||
|
|
||||||
function initializeDatabases(cb) {
|
function initializeDatabases(cb) {
|
||||||
async.each( [ 'system', 'user', 'message', 'file' ], (dbName, next) => {
|
async.each( [ 'system', 'user', 'message', 'file' ], (dbName, next) => {
|
||||||
dbs[dbName] = new sqlite3.Database(getDatabasePath(dbName), err => {
|
dbs[dbName] = new sqlite3.Database(getDatabasePath(dbName), err => {
|
||||||
|
@ -257,7 +264,6 @@ const DB_INIT_TABLE = {
|
||||||
file_name, /* FTS @ file_fts */
|
file_name, /* FTS @ file_fts */
|
||||||
desc, /* FTS @ file_fts */
|
desc, /* FTS @ file_fts */
|
||||||
desc_long, /* FTS @ file_fts */
|
desc_long, /* FTS @ file_fts */
|
||||||
upload_by_username VARCHAR NOT NULL,
|
|
||||||
upload_timestamp DATETIME NOT NULL
|
upload_timestamp DATETIME NOT NULL
|
||||||
);`
|
);`
|
||||||
);
|
);
|
||||||
|
|
|
@ -156,28 +156,35 @@ function sliceAtSauceMarker(data) {
|
||||||
return data.slice(0, eof);
|
return data.slice(0, eof);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getEstYear(input) {
|
function attemptSetEstimatedReleaseDate(fileEntry) {
|
||||||
// :TODO: yearEstPatterns RegExp's should be cached - we can do this @ Config (re)load time
|
// :TODO: yearEstPatterns RegExp's should be cached - we can do this @ Config (re)load time
|
||||||
const patterns = Config.fileBase.yearEstPatterns.map( p => new RegExp(p, 'gmi'));
|
const patterns = Config.fileBase.yearEstPatterns.map( p => new RegExp(p, 'gmi'));
|
||||||
|
|
||||||
let match;
|
function getMatch(input) {
|
||||||
for(let i = 0; i < patterns.length; ++i) {
|
if(input) {
|
||||||
match = patterns[i].exec(input);
|
let m;
|
||||||
if(match) {
|
for(let i = 0; i < patterns.length; ++i) {
|
||||||
break;
|
m = patterns[i].exec(input);
|
||||||
|
if(m) {
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(match) {
|
//
|
||||||
if(2 == match[1].length) {
|
// We attempt deteciton in short -> long order
|
||||||
return parseInt('19' + match[1]);
|
//
|
||||||
} else {
|
const match = getMatch(fileEntry.desc) || getMatch(fileEntry.descLong);
|
||||||
return parseInt(match[1]);
|
if(match && match[1]) {
|
||||||
|
const year = (2 === match[1].length) ? parseInt('19' + match[1]) : parseInt(match[1]);
|
||||||
|
if(year) {
|
||||||
|
fileEntry.meta.est_release_year = year;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addNewArchiveFileEnty(fileEntry, filePath, archiveType, cb) {
|
function populateFileEntryWithArchive(fileEntry, filePath, archiveType, cb) {
|
||||||
const archiveUtil = ArchiveUtil.getInstance();
|
const archiveUtil = ArchiveUtil.getInstance();
|
||||||
|
|
||||||
async.waterfall(
|
async.waterfall(
|
||||||
|
@ -258,10 +265,8 @@ function addNewArchiveFileEnty(fileEntry, filePath, archiveType, cb) {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
function attemptReleaseYearEstimation(callback) {
|
function attemptReleaseYearEstimation(callback) {
|
||||||
let estYear;
|
attemptSetEstimatedReleaseDate(fileEntry);
|
||||||
if(fileEntry.descLong) {
|
return callback(null);
|
||||||
estYear = getEstYear(fileEntry.descLong);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
err => {
|
err => {
|
||||||
|
@ -270,17 +275,47 @@ function addNewArchiveFileEnty(fileEntry, filePath, archiveType, cb) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function populateFileEntry(fileEntry, filePath, archiveType, cb) {
|
||||||
|
// :TODO: implement me!
|
||||||
|
return cb(null);
|
||||||
|
}
|
||||||
|
|
||||||
function addNewFileEntry(fileEntry, filePath, cb) {
|
function addNewFileEntry(fileEntry, filePath, cb) {
|
||||||
const archiveUtil = ArchiveUtil.getInstance();
|
const archiveUtil = ArchiveUtil.getInstance();
|
||||||
|
|
||||||
// :TODO: Use detectTypeWithBuf() once avail - we *just* read some file data
|
// :TODO: Use detectTypeWithBuf() once avail - we *just* read some file data
|
||||||
archiveUtil.detectType(filePath, (err, archiveType) => {
|
|
||||||
if(archiveType) {
|
async.series(
|
||||||
return addNewArchiveFileEnty(fileEntry, filePath, archiveType, cb);
|
[
|
||||||
} else {
|
function populateInfo(callback) {
|
||||||
// :TODO:addNewNonArchiveFileEntry
|
archiveUtil.detectType(filePath, (err, archiveType) => {
|
||||||
}
|
if(archiveType) {
|
||||||
});
|
populateFileEntryWithArchive(fileEntry, filePath, archiveType, err => {
|
||||||
|
if(err) {
|
||||||
|
populateFileEntry(fileEntry, filePath, err => {
|
||||||
|
// :TODO: log err
|
||||||
|
return callback(null); // ignore err
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return callback(null);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
populateFileEntry(fileEntry, filePath, err => {
|
||||||
|
// :TODO: log err
|
||||||
|
return callback(null); // ignore err
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function addNewDbRecord(callback) {
|
||||||
|
return fileEntry.persist(callback);
|
||||||
|
}
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateFileEntry(fileEntry, filePath, cb) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addOrUpdateFileEntry(areaInfo, fileName, options, cb) {
|
function addOrUpdateFileEntry(areaInfo, fileName, options, cb) {
|
||||||
|
@ -289,6 +324,7 @@ function addOrUpdateFileEntry(areaInfo, fileName, options, cb) {
|
||||||
areaTag : areaInfo.areaTag,
|
areaTag : areaInfo.areaTag,
|
||||||
meta : options.meta,
|
meta : options.meta,
|
||||||
hashTags : options.hashTags, // Set() or Array
|
hashTags : options.hashTags, // Set() or Array
|
||||||
|
fileName : fileName,
|
||||||
});
|
});
|
||||||
|
|
||||||
const filePath = paths.join(getAreaStorageDirectory(areaInfo), fileName);
|
const filePath = paths.join(getAreaStorageDirectory(areaInfo), fileName);
|
||||||
|
@ -302,8 +338,7 @@ function addOrUpdateFileEntry(areaInfo, fileName, options, cb) {
|
||||||
const sha1 = crypto.createHash('sha1');
|
const sha1 = crypto.createHash('sha1');
|
||||||
const sha256 = crypto.createHash('sha256');
|
const sha256 = crypto.createHash('sha256');
|
||||||
const md5 = crypto.createHash('md5');
|
const md5 = crypto.createHash('md5');
|
||||||
|
|
||||||
|
|
||||||
// :TODO: crc32
|
// :TODO: crc32
|
||||||
|
|
||||||
stream.on('data', data => {
|
stream.on('data', data => {
|
||||||
|
@ -340,17 +375,6 @@ function addOrUpdateFileEntry(areaInfo, fileName, options, cb) {
|
||||||
if(existingEntries.length > 0) {
|
if(existingEntries.length > 0) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//
|
|
||||||
// Some basics for new entries
|
|
||||||
//
|
|
||||||
fileEntry.meta.user_rating = 0;
|
|
||||||
if(options.uploadByUserName) {
|
|
||||||
fileEntry.meta.upload_by_username = options.uploadByUserName;
|
|
||||||
}
|
|
||||||
if(options.uploadByUserId) {
|
|
||||||
fileEntry.meta.upload_by_user_id = options.uploadByUserId;
|
|
||||||
}
|
|
||||||
|
|
||||||
return addNewFileEntry(fileEntry, filePath, callback);
|
return addNewFileEntry(fileEntry, filePath, callback);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
/* jslint node: true */
|
/* jslint node: true */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const fileDb = require('./database.js').dbs.file;
|
const fileDb = require('./database.js').dbs.file;
|
||||||
const Errors = require('./enig_error.js').Errors;
|
const Errors = require('./enig_error.js').Errors;
|
||||||
|
const getISOTimestampString = require('./database.js').getISOTimestampString;
|
||||||
|
|
||||||
// deps
|
// deps
|
||||||
const async = require('async');
|
const async = require('async');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
|
||||||
const FILE_TABLE_MEMBERS = [
|
const FILE_TABLE_MEMBERS = [
|
||||||
'file_id', 'area_tag', 'file_sha1', 'file_name',
|
'file_id', 'area_tag', 'file_sha1', 'file_name',
|
||||||
'desc', 'desc_long', 'upload_by_username', 'upload_timestamp' // :TODO: remove upload_by_username -- and from database.js, etc.
|
'desc', 'desc_long', 'upload_timestamp'
|
||||||
];
|
];
|
||||||
|
|
||||||
const FILE_WELL_KNOWN_META = {
|
const FILE_WELL_KNOWN_META = {
|
||||||
|
@ -34,6 +35,7 @@ module.exports = class FileEntry {
|
||||||
this.areaTag = options.areaTag || '';
|
this.areaTag = options.areaTag || '';
|
||||||
this.meta = {};
|
this.meta = {};
|
||||||
this.hashTags = new Set();
|
this.hashTags = new Set();
|
||||||
|
this.fileName = options.fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
load(fileId, cb) {
|
load(fileId, cb) {
|
||||||
|
@ -79,6 +81,58 @@ module.exports = class FileEntry {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
persist(cb) {
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
async.series(
|
||||||
|
[
|
||||||
|
function startTrans(callback) {
|
||||||
|
return fileDb.run('BEGIN;', callback);
|
||||||
|
},
|
||||||
|
function storeEntry(callback) {
|
||||||
|
fileDb.run(
|
||||||
|
`REPLACE INTO file (area_tag, file_sha1, file_name, desc, desc_long, upload_timestamp)
|
||||||
|
VALUES(?, ?, ?, ?, ?, ?);`,
|
||||||
|
[ self.areaTag, self.fileSha1, self.fileName, self.desc, self.descLong, getISOTimestampString() ],
|
||||||
|
function inserted(err) { // use non-arrow func for 'this' scope / lastID
|
||||||
|
if(!err) {
|
||||||
|
self.fileId = this.lastID;
|
||||||
|
}
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
function storeMeta(callback) {
|
||||||
|
async.each(Object.keys(self.meta), (n, next) => {
|
||||||
|
const v = self.meta[n];
|
||||||
|
return FileEntry.persistMetaValue(self.fileId, n, v, next);
|
||||||
|
},
|
||||||
|
err => {
|
||||||
|
return callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function storeHashTags(callback) {
|
||||||
|
return callback(null);
|
||||||
|
}
|
||||||
|
],
|
||||||
|
err => {
|
||||||
|
// :TODO: Log orig err
|
||||||
|
fileDb.run(err ? 'ROLLBACK;' : 'COMMIT;', err => {
|
||||||
|
return cb(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static persistMetaValue(fileId, name, value, cb) {
|
||||||
|
fileDb.run(
|
||||||
|
`REPLACE INTO file_meta (file_id, meta_name, meta_value)
|
||||||
|
VALUES(?, ?, ?);`,
|
||||||
|
[ fileId, name, value ],
|
||||||
|
cb
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
loadMeta(cb) {
|
loadMeta(cb) {
|
||||||
fileDb.each(
|
fileDb.each(
|
||||||
`SELECT meta_name, meta_value
|
`SELECT meta_name, meta_value
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
/* jslint node: true */
|
/* jslint node: true */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let msgDb = require('./database.js').dbs.message;
|
const msgDb = require('./database.js').dbs.message;
|
||||||
let wordWrapText = require('./word_wrap.js').wordWrapText;
|
const wordWrapText = require('./word_wrap.js').wordWrapText;
|
||||||
let ftnUtil = require('./ftn_util.js');
|
const ftnUtil = require('./ftn_util.js');
|
||||||
let createNamedUUID = require('./uuid_util.js').createNamedUUID;
|
const createNamedUUID = require('./uuid_util.js').createNamedUUID;
|
||||||
|
const getISOTimestampString = require('./database.js').getISOTimestampString;
|
||||||
|
|
||||||
let uuid = require('node-uuid');
|
// deps
|
||||||
let async = require('async');
|
const uuid = require('node-uuid');
|
||||||
let _ = require('lodash');
|
const async = require('async');
|
||||||
let assert = require('assert');
|
const _ = require('lodash');
|
||||||
let moment = require('moment');
|
const assert = require('assert');
|
||||||
const iconvEncode = require('iconv-lite').encode;
|
const moment = require('moment');
|
||||||
|
const iconvEncode = require('iconv-lite').encode;
|
||||||
|
|
||||||
module.exports = Message;
|
module.exports = Message;
|
||||||
|
|
||||||
|
@ -64,11 +66,6 @@ function Message(options) {
|
||||||
this.isPrivate = function() {
|
this.isPrivate = function() {
|
||||||
return Message.isPrivateAreaTag(this.areaTag);
|
return Message.isPrivateAreaTag(this.areaTag);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getMessageTimestampString = function(ts) {
|
|
||||||
ts = ts || moment();
|
|
||||||
return ts.format('YYYY-MM-DDTHH:mm:ss.SSSZ');
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Message.WellKnownAreaTags = {
|
Message.WellKnownAreaTags = {
|
||||||
|
@ -374,7 +371,7 @@ Message.prototype.persist = function(cb) {
|
||||||
msgDb.run(
|
msgDb.run(
|
||||||
`INSERT INTO message (area_tag, message_uuid, reply_to_message_id, to_user_name, from_user_name, subject, message, modified_timestamp)
|
`INSERT INTO message (area_tag, message_uuid, reply_to_message_id, to_user_name, from_user_name, subject, message, modified_timestamp)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?);`,
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?);`,
|
||||||
[ self.areaTag, self.uuid, self.replyToMsgId, self.toUserName, self.fromUserName, self.subject, self.message, self.getMessageTimestampString(msgTimestamp) ],
|
[ self.areaTag, self.uuid, self.replyToMsgId, self.toUserName, self.fromUserName, self.subject, self.message, getISOTimestampString(msgTimestamp) ],
|
||||||
function inserted(err) { // use non-arrow function for 'this' scope
|
function inserted(err) { // use non-arrow function for 'this' scope
|
||||||
if(!err) {
|
if(!err) {
|
||||||
self.messageId = this.lastID;
|
self.messageId = this.lastID;
|
||||||
|
|
Loading…
Reference in New Issue