var sqlite = require('sqlite3').verbose(); var async = require('async'); var config = require('./config.js').config; var helper = require('./helper.js'); var db = new sqlite.Database(config.dbPath); // Function to get a user record by the username and password // Returns SQL row for that user exports.getUser = function(username, password, cb) { db.get('SELECT salt FROM users WHERE username = ?', username, function(err, row) { var hash = helper.hashPassword(password, row.salt); db.get('SELECT username, id, displayName, createDate \ FROM users WHERE username = ? AND password = ?', username, hash, function(err, row) { cb(row); }); }); } // Function to get a user record by id, does not validate user password // Returns SQL row for that user exports.getUserById = function(id, cb) { db.get('SELECT username, id, displayName, createDate \ FROM users WHERE id = ?', id, function(err, row) { cb(row); }); } // Function to get the latest regenerate date // Returns a epoch time in seconds exports.getLastRegenerateDate = function(cb) { db.get('SELECT MAX(lastGenerateDate) as date FROM ( \ SELECT lastGenerateDate FROM posts \ UNION \ SELECT lastGenerateDate FROM photos \ UNION \ SELECT lastGenerateDate FROM galleries);', function(err, row) { cb(row); }); } // Function to get the latest upload date // Returns a epoch time in seconds exports.getLastUploadDate = function(cb) { db.get('SELECT MAX(lastUpload) as date FROM ( \ SELECT lastUpload FROM posts \ UNION \ SELECT lastUpload FROM photos \ UNION \ SELECT lastUpload FROM galleries);', function(err, row) { cb(row); }); } // Function to get a count of current posts // Returns count of posts exports.countPosts = function(cb) { db.get('SELECT count(id) as count FROM posts;', function(err, count) { cb(count.count); }); } // Function to get a count of current galleries // Returns count of galleries exports.countGalleries = function(cb) { db.get('SELECT count(id) as count FROM galleries;', function(err, count) { cb(count.count); }); } // Function to get a count of current categories // Returns count of categories exports.countCategories = function(cb) { db.get('SELECT count(id) as count FROM categories;', function(err, count) { cb(count.count); }); } // Function to get a count of current photos // Returns count of tags exports.countPhotos = function(cb) { db.get('SELECT count(id) as count FROM photos;', function(err, count) { cb(count.count); }); } // Function to get a count of current tags // Returns count of tags exports.countTags = function(cb) { db.get('SELECT count(id) as count FROM tags;', function(err, count) { cb(count.count); }); } // Function to get all categories including their ID and descriptions // Returns array of rows of categories exports.listCategories = function(cb) { db.all('SELECT * FROM CATEGORIES', function(err, rows) { cb(rows); }); } // Function to get a list of posts of a certain count and starting at an offset // Returns a list of post objects exports.listPosts = function(count, start, cb) { db.all('SELECT * FROM posts ORDER BY postDate DESC, title ASC \ LIMIT '+count+' OFFSET '+start+';', function(err, posts) { console.log(err); cb(posts); }); } // Function to get a list of photos of a certain count and starting at an offset // Returns a list of photo objects exports.listPhotos = function(count, start, cb) { db.all('SELECT * FROM photos ORDER BY photoDate DESC, title ASC \ LIMIT '+count+' OFFSET '+start+';', function(err, photos) { console.log(err); cb(photos); }); } // NON-EXPORTED function to create a category if it does not exist // Returns a row of category information var getOrCreateCategory = function(name, cb) { db.get('SELECT * FROM categories WHERE name = "'+name+'";', function(err, row) { if (!err && row) { console.log('Category '+name+' exists.'); cb(row); } else { console.log('Category '+name+' does not exist. Creating...'); epoch = helper.dateToEpoch(new Date()); db.run('INSERT INTO categories (\ name, slug, createDate \ ) VALUES (\ "'+name+'", \ "'+helper.makeSlug(name)+'", \ '+epoch+');', function(err, row) { if (err) { console.log(err); } else { console.log('Category '+name+' created.'); db.get('SELECT * FROM categories WHERE name = "'+name+'";', function(err, row){ cb(row); }) } }) } }) } // Function to set a category for a post given a post id and a category name // Returns error code exports.setPostCategory = function(postId, categoryName, cb) { console.log('Setting post '+postId+' category to '+categoryName); getOrCreateCategory(categoryName, function(category) { db.get('SELECT categoryId FROM categoryPosts \ WHERE postId = '+postId+';', function(err, row) { if (row) { console.log('Post '+postId+' has assigned category of '+row.categoryId); if (row.categoryId == category.id) { console.log('Current post category is the same as new post category, no update necessary.'); cb(null); } else { console.log("Current post category ("+row.categoryId+") doesn't match new category ("+category.id+"), updating record."); db.run('UPDATE categoryPosts SET \ categoryId = '+category.id+' \ WHERE postId = '+postId+';', function(err) { if (err) { console.log(err); } else { console.log("Category updated."); cb(null); } }); } } else { console.log('Post '+postId+' has no category assigned. Inserting record.'); db.run('INSERT INTO categoryPosts (postId, categoryId) VALUES ('+postId+', '+category.id+');', function(err) { if (err) { console.log(err); } else { console.log('Post '+postId+' assigned to category '+category.id); cb(null); } }); } }) }); } // Function to create a new post // Returns the post id exports.createPost = function(title, slug, markdown, postDate, updatedDate, createDate, cb) { db.run('INSERT INTO posts (\ title, \ slug, \ markdown, \ postDate, \ createDate, \ updatedDate, \ lastGenerateDate, \ lastUpload) \ VALUES (\ "'+title+'", \ "'+slug+'", \ "'+markdown+'", \ "'+postDate+'", \ "'+createDate+'", \ "'+updatedDate+'", \ (strftime("%s","1900-01-01 00:00")*1000), \ (strftime("%s","1900-01-01 00:00")*1000));', function(err, row) { if (err) console.log(err); db.get('SELECT * FROM posts WHERE title = "'+title+'" AND createDate = '+createDate+';', function(err, row){ cb(err, row); }) }); } // Function to update an existing post record // Returns the post object exports.updatePost = function(id, title, slug, markdown, postDate, cb) { console.log("updatePost called."); db.run('UPDATE posts SET \ title = "'+title+'", \ slug = "'+slug+'", \ markdown = "'+markdown+'", \ postDate = '+helper.dateToEpoch(postDate)+', \ updatedDate = '+helper.dateToEpoch(new Date())+' \ WHERE id = '+id+';', function(err) { console.log('updatePost UPDATE result: '+err); db.get('SELECT * FROM posts WHERE id = '+id+';', function(err, row) { console.log('updatePost SELECT result: ' + err); cb(row); }); }); } // Function to get a post record by the id of the post // Returns the post record exports.getPostById = function(id, cb) { db.get('SELECT * FROM posts WHERE id = ?', id, function(err, row) { cb(row); }); } // Function to get a category record given a post id // Returns the first category record associated with the post. exports.getPostCategory = function(id, cb) { db.get('SELECT * FROM categories WHERE id = (\ SELECT categoryId FROM categoryPosts WHERE postId = '+id+');', function(err, row) { if (err) { console.log(err); } if (row) { console.log('Post '+id+' category is '+row.name); cb(row); } else { cb(null); } }); } // Function to get record of a tag, inserting it if required. // Inputs are a tag name and a callback. // Returns the created tag record. var getOrCreateTag = function(tag, cb) { var slug = helper.makeSlug(tag); db.get('SELECT * from tags WHERE slug = "'+slug+'" LIMIT 1;', function(err, row) { if (err) { console.log(err); } if (row) { console.log(slug+' tag exists'); cb(row); } else { db.run('INSERT INTO tags (name, slug, createDate) \ VALUES ("'+tag+'", "'+slug+'", '+ helper.dateToEpoch(new Date()) +');', function(err, id) { if (!err) { console.log(slug+' tag created'); db.get('SELECT * FROM tags WHERE slug = "'+slug+'" LIMIT 1;', function (err, row) { if (err) console.log(err); if (row) cb(row); }); }; }); } }) } exports.getOrCreateTag = getOrCreateTag; // Function to tag a post with a list of tag names // Inputs: Post ID, List of Tag names // Does not return. exports.tagPost = function (postId, tags) { console.log('Deleting old tags'); db.run('DELETE FROM postTags WHERE postId = '+postId+';', function(err) { console.log('Old tags deleted'); for (var i = 0, size = tags.length; i < size; i++) { getOrCreateTag(tags[i], function(row) { db.run('INSERT INTO postTags (postId, tagId) \ VALUES ('+postId+', '+row.id+');', function(err) { if (err) { console.log(err); } else { console.log('Post '+postId+' tagged as '+row.name); } }); }); } }); } // Function to get tag ids associated with a particular post id // Inputs: Post ID // Returns: Records associated with tags of that post id var getPostTags = function (postId, cb) { db.all('SELECT tagId FROM postTags WHERE postId = '+postId+';', function(err, rows) { if (err) { console.log(err); } else { var tagList = []; for (row in rows) { tagList.push(rows[row].tagId); } tagList = tagList.join(', '); console.log('Tag ids for '+postId+': '+tagList); db.all('SELECT * FROM tags WHERE id IN ('+tagList+');', function(err, rows) { if (err) { console.log(err); } else { cb(rows); } }) } }) } exports.getPostTags = getPostTags; // Function that returns all the post tags as a space separated string. // Inputs: Post ID, callback function. // Returns: callback of string with all tags separated by spaces. var getPostTagsAsString = function(postId, cb) { getPostTags(postId, function(tags) { var str = false; for (tag in tags) { if (!str) { str = tags[tag].name; } else { str = str + ' ' + tags[tag].name; } } console.log("Tags for "+postId+": "+str); cb(str); }) } exports.getPostTagsAsString = getPostTagsAsString; // Function to tag a photo with a list of tag names // Inputs: Photo ID, List of Tag names // Does not return. exports.tagPhoto = function (photoId, tags) { console.log('Deleting old tags'); db.run('DELETE FROM photoTags WHERE photoId = '+photoId+';', function(err) { console.log('Old tags deleted'); for (var i = 0, size = tags.length; i < size; i++) { getOrCreateTag(tags[i], function(row) { db.run('INSERT INTO photoTags (photoId, tagId) \ VALUES ('+photoId+', '+row.id+');', function(err) { if (err) { console.log(err); } else { console.log('Photo '+photoId+' tagged as '+row.name); } }); }); } }); } // Function to get tag ids associated with a particular photo id // Inputs: Photo ID // Returns: Records associated with tags of that photo id var getPhotoTags = function (photoId, cb) { db.all('SELECT tagId FROM photoTags WHERE photoId = '+photoId+';', function(err, rows) { if (err) { console.log(err); } else { var tagList = []; for (row in rows) { tagList.push(rows[row].tagId); } tagList = tagList.join(', '); console.log('Tag ids for photo '+photoId+': '+tagList); db.all('SELECT * FROM tags WHERE id IN ('+tagList+');', function(err, rows) { if (err) { console.log(err); } else { cb(rows); } }) } }) } exports.getPhotoTags = getPhotoTags; // Function that returns all the photo tags as a space separated string. // Inputs: Photo ID, callback function. // Returns: callback of string with all tags separated by spaces. var getPhotoTagsAsString = function(photoId, cb) { getPhotoTags(photoId, function(tags) { var str = false; for (tag in tags) { if (!str) { str = tags[tag].name; } else { str = str + ' ' + tags[tag].name; } } console.log("Tags for photo "+photoId+": "+str); cb(str); }) } exports.getPhotoTagsAsString = getPhotoTagsAsString; // Function to get a photo record by the id of the photo // Returns the photo record exports.getPhotoById = function(id, cb) { db.get('SELECT * FROM photos WHERE id = ?', id, function(err, row) { if (err) console.log(err); cb(row); }); } // Function to create a new photo // Returns the photo id exports.createPhoto = function(title, slug, markdown, extension, mimetype, photoDate, updatedDate, createDate, path, cb) { console.log('Creating new photo: '+slug); db.run('INSERT INTO photos (\ title, \ slug, \ description, \ path, \ extension, \ mimetype, \ photoDate, \ createDate, \ updatedDate, \ lastGenerateDate, \ lastUpload) \ VALUES (\ "'+title+'", \ "'+slug+'", \ "'+markdown+'", \ "'+path+'", \ "'+extension+'", \ "'+mimetype+'", \ "'+photoDate+'", \ "'+createDate+'", \ "'+updatedDate+'", \ (strftime("%s","1900-01-01 00:00")*1000), \ (strftime("%s","1900-01-01 00:00")*1000));', function(err, row) { if (!err) { console.log('Photo '+slug+' created.'); } else { console.log('Error: '+err); } db.get('SELECT * FROM photos WHERE title = "'+title+'" AND createDate = '+createDate+';', function(err, row){ if (err) console.log(err); cb(err, row); }) }); } // Function to update an existing post record // Returns the post object exports.updatePhoto = function(id, title, slug, markdown, photoDate, cb) { console.log("updatePost called."); db.run('UPDATE photos SET \ title = "'+title+'", \ slug = "'+slug+'", \ description = "'+markdown+'", \ photoDate = '+helper.dateToEpoch(photoDate)+', \ updatedDate = '+helper.dateToEpoch(new Date())+' \ WHERE id = '+id+';', function(err) { console.log('updatePhoto UPDATE result: '+err); db.get('SELECT * FROM photos WHERE id = '+id+';', function(err, row) { console.log('updatePhoto SELECT result: ' + err); cb(row); }); }); }