Guest User

Untitled

a guest
Sep 22nd, 2018
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.90 KB | None | 0 0
  1. var pg = require('pg');
  2. var async = require('async');
  3.  
  4.  
  5. exports.DB_ERROR = 1;
  6. exports.SAME_USER_CONTINUE = 2;
  7. exports.WORD_NOT_CONTINUE = 3;
  8. exports.RECORD_NOT_FOUND = 4;
  9. exports.INVALID_URL_PARAM = 5;
  10.  
  11. function word_database(client, settings) {
  12. var self = this;
  13. self.client = client;
  14. self.client.connect();
  15. self.settings = settings;
  16. }
  17.  
  18. var insert_into_entry = function(self, respond_cb, parent_msgid, word_id, user_id, stats) {
  19. //console.log("params:" + parent_msgid + "," + word_id + "," + user_id);
  20. self.client.query("INSERT INTO " + self.settings.entry_db_name +
  21. " (prev_id, word_id, user_id, depth) " +
  22. "VALUES(" + parent_msgid + "," + word_id + "," + user_id + "," + stats.depth + ");",
  23. function (err, result) {
  24. if (err) {
  25. respond_cb({msg_id: null, error:{text:err.stack, code:exports.DB_ERROR}});
  26. }
  27. else {
  28. var qq = self.client.query("SELECT LASTVAL();");
  29. qq.on("row", function(row) {
  30. respond_cb({msg_id: row.lastval, stats:stats});
  31. });
  32. }
  33. }
  34. );
  35. }
  36.  
  37. var validate_word = function(self, respond_cb, word, parent_msgid, user_id, on_success) {
  38. if (!parent_msgid) {
  39. on_success(null);
  40. return;
  41. }
  42. var q = self.client.query("SELECT * FROM " + self.settings.entry_db_name + " WHERE id=" + parent_msgid + ";");
  43. var selected = null;
  44. q.on('row', function (row) {
  45. selected = row;
  46. });
  47. q.on('end', function () {
  48. if (selected) {
  49. if (selected.user_id == user_id) {
  50. respond_cb({msg_id:null, error:{text:"cannot continue of same user's post",code:exports.SAME_USER_CONTINUE}});
  51. return;
  52. }
  53. var wq = self.client.query("SELECT * FROM " + self.settings.word_db_name + " WHERE id='" + selected.word_id + "';");
  54. var word_selected = null;
  55. wq.on('row', function (row) {
  56. word_selected = row;
  57. });
  58. wq.on('end', function () {
  59. console.log(JSON.stringify(word_selected));
  60. if (word_selected.word[word_selected.word.length - 1] != word[0]) {
  61. respond_cb({msg_id:null,
  62. error:{text:'word is not continue:' + word_selected.word + ' and ' + word, code:exports.WORD_NOT_CONTINUE}});
  63. return;
  64. }
  65. on_success(selected);
  66. });
  67. }
  68. else {
  69. respond_cb({msg_id:null,
  70. error:{text:'invalid id(' + parent_msgid + ') not found in database', code:exports.RECORD_NOT_FOUND}});
  71. }
  72. });
  73. }
  74.  
  75. /*
  76. register shiritori word into database
  77. args: word string: word to insert db
  78. fb_user_id int: facebook user id
  79. msg_id int: which shiritori entry that arg 'word' try to continue?
  80. respond_cb function: both success and error, JSON is returned.
  81. format:
  82. {msg_id:integer(success) or nil(error),
  83. error:{text:{error explanation}, code:{error code (integer)} (if error)
  84. stats:{depth:(node depth ( == how many times continue - 1)),
  85. word:(registered word),
  86. word_count:(how many times appeard)}
  87.  
  88. */
  89. word_database.prototype.register_word = function(word, fb_user_id, msg_id, respond_cb) {
  90. var self = this;
  91. if (!word || !fb_user_id) {
  92. respond_cb({msg_id:null, error:{text:'required parameter not specified',code:exports.INVALID_URL_PARAM}});
  93. return;
  94. }
  95. if (!msg_id) {
  96. msg_id = 0;
  97. }
  98. console.log("params: " + word + "," + fb_user_id + "," + msg_id);
  99.  
  100. validate_word(self, respond_cb, word, msg_id, fb_user_id, function (prev_entry) {
  101. var q = self.client.query("SELECT * FROM " + self.settings.word_db_name + " WHERE word='" + word + "';");
  102. var selected = null;
  103. q.on('row', function(row) {
  104. selected = row;
  105. });
  106. q.on('end', function() {
  107. if (selected) {
  108. self.client.query("UPDATE " + self.settings.word_db_name + " SET count = count + 1 WHERE id = " + selected.id);
  109. insert_into_entry(self, respond_cb, msg_id, selected.id, fb_user_id,
  110. {depth:(prev_entry ? (prev_entry.depth + 1) : 0), word_count:selected.count + 1, word:word});
  111. }
  112. else {
  113. self.client.query("INSERT INTO " + self.settings.word_db_name + "(word,count) VALUES('" + word + "', 1);");
  114. var qq = self.client.query("SELECT LASTVAL();");
  115. qq.on('row', function(row) {
  116. insert_into_entry(self, respond_cb, msg_id, row.lastval, fb_user_id,
  117. {depth:(prev_entry ? (prev_entry.depth + 1) : 0), word_count:1, word:word});
  118. });
  119. }
  120. });
  121. });
  122. }
  123.  
  124. /*
  125. get data of specified shiritori entry
  126. args: msg_id: integer: id of entry which you want to retrieve its content.
  127. respond_cb function(JSON): callback function
  128. format: {
  129. id:(id of entry, which should be equals to msg_id)
  130. prev_id:(parent entry id)
  131. word_id:(primary key of words table)
  132. user_id:(facebook user_id)
  133. wdata:{
  134. id:(primary key of words table, which should be equals to word_id)
  135. word:(actual word value)
  136. count:(appeared count of entire shiritori tree)
  137. }
  138. }
  139.  
  140. */
  141. word_database.prototype.get_entry = function (msg_id, respond_cb) {
  142. var self = this;
  143. var q = self.client.query("SELECT * FROM " + self.settings.entry_db_name + " WHERE id=" + msg_id + ";");
  144. var selected = null;
  145. q.on('row', function (row) {
  146. selected = row;
  147. });
  148. q.on('end', function () {
  149. if (selected) {
  150. var wq = self.client.query("SELECT * FROM " + self.settings.word_db_name + " WHERE id=" + selected.word_id + ";");
  151. wq.on('row', function (row) {
  152. selected.wdata = row;
  153. });
  154. wq.on('end', function () {
  155. respond_cb(selected);
  156. });
  157. }
  158. else {
  159. respond_cb(null);
  160. }
  161. });
  162. }
  163.  
  164.  
  165. function get_history_helper(self, msgid, context, respond_cb) {
  166. var selected = null;
  167. var q = self.client.query("SELECT * FROM " + self.settings.entry_db_name + " WHERE id=" + msgid + ";");
  168. q.on('row', function (row) {
  169. selected = row;
  170. });
  171. q.on('end', function () {
  172. if (selected) {
  173. var wq = self.client.query("SELECT * FROM " + self.settings.word_db_name + " WHERE id=" + selected.word_id + ";");
  174. wq.on('row', function (row) {
  175. selected.wdata = row;
  176. });
  177. wq.on('end', function () {
  178. context.histories.push(selected);
  179. context.remain = (context.remain - 1);
  180. if (context.remain <= 0 || selected.prev_id == 0) {
  181. respond_cb(context.histories);
  182. }
  183. else {
  184. get_history_helper(self, selected.prev_id, context, respond_cb);
  185. }
  186. });
  187. }
  188. else {
  189. respond_cb(null);
  190. }
  191. });
  192. }
  193.  
  194. /*
  195. get shiritori history of anccester of specified entry
  196. args: start_msgid: integer: specify start entry
  197. count: integer > 0:how many history of entry retrieved?
  198. respond_cb function(JSON): callback
  199. format: same as get_entry's, but array.
  200. */
  201. word_database.prototype.get_history = function (start_msgid, count, respond_cb) {
  202. var self = this;
  203. var context = { histories:[], remain:count };
  204. get_history_helper(self, start_msgid, context, respond_cb);
  205. }
  206.  
  207.  
  208. exports.create = function (ns, re_create, callback) {
  209. var word_seq_name = "word_id_seq";
  210. var word_db_name = "words";
  211. var entry_seq_name = "entry_id_seq";
  212. var entry_db_name = "entries";
  213. if (ns) {
  214. word_seq_name = (ns + "_word_id_seq");
  215. word_db_name = (ns + "_words");
  216. entry_seq_name =(ns + "_entry_id_seq");
  217. entry_db_name = (ns + "_entries");
  218. }
  219.  
  220. pg.connect(process.env.DATABASE_URL, function(err, client) {
  221. function init_word_database(cb) {
  222. client.query((re_create ? "DROP SEQUENCE IF EXISTS " + word_seq_name + ";" : "") +
  223. "CREATE SEQUENCE " + word_seq_name + ";",
  224. function (err, result) {
  225. client.query(
  226. (re_create ? "DROP TABLE IF EXISTS " + word_db_name + ";" : "") +
  227. "CREATE TABLE " + word_db_name + " (" +
  228. "id INTEGER DEFAULT nextval('" + word_seq_name + "') PRIMARY KEY," +
  229. "word VARCHAR(32) NOT NULL UNIQUE," +
  230. "count int NOT NULL" +
  231. ");",
  232. cb);
  233. }
  234. );
  235. }
  236. function init_entry_database(cb) {
  237. client.query((re_create ? "DROP SEQUENCE IF EXISTS " + entry_seq_name + ";" : "") +
  238. "CREATE SEQUENCE " + entry_seq_name + ";",
  239. function (err, result) {
  240. client.query(
  241. (re_create ? "DROP TABLE IF EXISTS " + entry_db_name + ";" : "") +
  242. "CREATE TABLE " + entry_db_name +" (" +
  243. "id INTEGER DEFAULT nextval('" + entry_seq_name + "') PRIMARY KEY," +
  244. "prev_id INT NOT NULL DEFAULT 0," +
  245. "word_id INT NOT NULL," +
  246. "user_id INT NOT NULL," +
  247. "depth INT NOT NULL DEFAULT 0" +
  248. ");",
  249. cb);
  250. }
  251. );
  252. }
  253. async.parallel([
  254. init_word_database,
  255. init_entry_database
  256. ], function(err, result) {
  257. if (err) {
  258. callback(err, null);
  259. return;
  260. }
  261. console.log("word_database module: create finished for namespace:" + ns);
  262. if (!re_create) {
  263. var wq = client.query("SELECT * FROM " + word_db_name +";");
  264. wq.on('row', function(row) {
  265. console.log("word_row:" + JSON.stringify(row));
  266. })
  267. var eq = client.query("SELECT * FROM " + entry_db_name + ";");
  268. eq.on('row', function(row) {
  269. console.log("entry_row:" + JSON.stringify(row));
  270. })
  271. }
  272. callback(null, new word_database(new pg.Client(process.env.DATABASE_URL), {
  273. word_seq_name: word_seq_name,
  274. word_db_name: word_db_name,
  275. entry_seq_name: entry_seq_name,
  276. entry_db_name: entry_db_name,
  277. }));
  278. });
  279. });
  280. }
Add Comment
Please, Sign In to add comment