database.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. const {defaultSettings} = require('./util/default.json');
  2. const sqlite3 = require('sqlite3').verbose();
  3. const mode = ( process.env.READONLY ? sqlite3.OPEN_READONLY : sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE );
  4. const schema = [`
  5. BEGIN TRANSACTION;
  6. CREATE TABLE patreons (
  7. patreon TEXT PRIMARY KEY
  8. UNIQUE
  9. NOT NULL,
  10. count INTEGER NOT NULL
  11. );
  12. CREATE INDEX idx_patreons_patreon ON patreons (
  13. patreon
  14. );
  15. CREATE TABLE discord (
  16. main TEXT UNIQUE
  17. CHECK (main = guild),
  18. guild TEXT NOT NULL
  19. REFERENCES discord (main) ON DELETE CASCADE,
  20. channel TEXT,
  21. wiki TEXT NOT NULL
  22. DEFAULT [${defaultSettings.wiki}],
  23. lang TEXT NOT NULL
  24. DEFAULT [${defaultSettings.lang}],
  25. role TEXT,
  26. inline INTEGER,
  27. prefix TEXT NOT NULL
  28. DEFAULT [${process.env.prefix}],
  29. patreon TEXT REFERENCES patreons (patreon) ON DELETE SET NULL,
  30. voice INTEGER,
  31. UNIQUE (
  32. guild,
  33. channel
  34. )
  35. );
  36. CREATE INDEX idx_discord_channel ON discord (
  37. guild,
  38. channel DESC
  39. );
  40. CREATE INDEX idx_discord_patreon ON discord (
  41. patreon
  42. )
  43. WHERE patreon IS NOT NULL;
  44. CREATE INDEX idx_discord_voice ON discord (
  45. voice
  46. )
  47. WHERE voice IS NOT NULL;
  48. CREATE TABLE verification (
  49. guild TEXT NOT NULL
  50. REFERENCES discord (main) ON DELETE CASCADE,
  51. configid INTEGER NOT NULL,
  52. channel TEXT NOT NULL,
  53. role TEXT NOT NULL,
  54. editcount INTEGER NOT NULL
  55. DEFAULT [0],
  56. postcount INTEGER DEFAULT [0],
  57. usergroup TEXT NOT NULL
  58. DEFAULT [user],
  59. accountage INTEGER NOT NULL
  60. DEFAULT [0],
  61. rename INTEGER NOT NULL
  62. DEFAULT [0],
  63. UNIQUE (
  64. guild,
  65. configid
  66. )
  67. );
  68. CREATE INDEX idx_verification_config ON verification (
  69. guild,
  70. configid ASC,
  71. channel
  72. );
  73. CREATE TABLE rcgcdw (
  74. guild TEXT NOT NULL
  75. REFERENCES discord (main) ON DELETE CASCADE,
  76. configid INTEGER NOT NULL,
  77. webhook TEXT NOT NULL
  78. UNIQUE,
  79. wiki TEXT NOT NULL,
  80. lang TEXT NOT NULL
  81. DEFAULT [${defaultSettings.lang}],
  82. display INTEGER NOT NULL
  83. DEFAULT [1],
  84. rcid INTEGER,
  85. postid TEXT DEFAULT [-1],
  86. UNIQUE (
  87. guild,
  88. configid
  89. )
  90. );
  91. CREATE INDEX idx_rcgcdw_wiki ON rcgcdw (
  92. wiki
  93. );
  94. CREATE INDEX idx_rcgcdw_webhook ON rcgcdw (
  95. webhook
  96. );
  97. CREATE INDEX idx_rcgcdw_config ON rcgcdw (
  98. guild,
  99. configid ASC
  100. );
  101. CREATE TABLE blocklist (
  102. wiki TEXT UNIQUE
  103. NOT NULL,
  104. reason TEXT
  105. );
  106. CREATE INDEX idx_blocklist_wiki ON blocklist (
  107. wiki
  108. );
  109. COMMIT TRANSACTION;
  110. PRAGMA user_version = 3;
  111. `,
  112. `
  113. BEGIN TRANSACTION;
  114. PRAGMA foreign_keys = OFF;
  115. UPDATE rcgcdw SET postid = '-1' WHERE wikiid IS NULL;
  116. CREATE TABLE rcgcdw_temp_table AS SELECT * FROM rcgcdw;
  117. DROP TABLE rcgcdw;
  118. CREATE TABLE rcgcdw (
  119. guild TEXT NOT NULL
  120. REFERENCES discord (main) ON DELETE CASCADE,
  121. configid INTEGER NOT NULL,
  122. webhook TEXT NOT NULL
  123. UNIQUE,
  124. wiki TEXT NOT NULL,
  125. lang TEXT NOT NULL
  126. DEFAULT [${defaultSettings.lang}],
  127. display INTEGER NOT NULL
  128. DEFAULT [1],
  129. rcid INTEGER,
  130. postid TEXT DEFAULT [-1],
  131. UNIQUE (
  132. guild,
  133. configid
  134. )
  135. );
  136. INSERT INTO rcgcdw (
  137. guild,
  138. configid,
  139. webhook,
  140. wiki,
  141. lang,
  142. display,
  143. rcid,
  144. postid
  145. )
  146. SELECT guild,
  147. configid,
  148. webhook,
  149. wiki,
  150. lang,
  151. display,
  152. rcid,
  153. postid
  154. FROM rcgcdw_temp_table;
  155. DROP TABLE rcgcdw_temp_table;
  156. CREATE INDEX idx_rcgcdw_wiki ON rcgcdw (
  157. wiki
  158. );
  159. CREATE INDEX idx_rcgcdw_webhook ON rcgcdw (
  160. webhook
  161. );
  162. CREATE INDEX idx_rcgcdw_config ON rcgcdw (
  163. guild,
  164. configid ASC
  165. );
  166. COMMIT TRANSACTION;
  167. PRAGMA user_version = 2;
  168. `,
  169. `
  170. BEGIN TRANSACTION;
  171. PRAGMA foreign_keys = OFF;
  172. CREATE TABLE verification_temp_table AS SELECT * FROM verification;
  173. DROP TABLE verification;
  174. CREATE TABLE verification (
  175. guild TEXT NOT NULL
  176. REFERENCES discord (main) ON DELETE CASCADE,
  177. configid INTEGER NOT NULL,
  178. channel TEXT NOT NULL,
  179. role TEXT NOT NULL,
  180. editcount INTEGER NOT NULL
  181. DEFAULT [0],
  182. postcount INTEGER DEFAULT [0],
  183. usergroup TEXT NOT NULL
  184. DEFAULT [user],
  185. accountage INTEGER NOT NULL
  186. DEFAULT [0],
  187. rename INTEGER NOT NULL
  188. DEFAULT [0],
  189. UNIQUE (
  190. guild,
  191. configid
  192. )
  193. );
  194. INSERT INTO verification (
  195. guild,
  196. configid,
  197. channel,
  198. role,
  199. editcount,
  200. usergroup,
  201. accountage,
  202. rename
  203. )
  204. SELECT guild,
  205. configid,
  206. channel,
  207. role,
  208. editcount,
  209. usergroup,
  210. accountage,
  211. rename
  212. FROM verification_temp_table;
  213. DROP TABLE verification_temp_table;
  214. CREATE INDEX idx_verification_config ON verification (
  215. guild,
  216. configid ASC,
  217. channel
  218. );
  219. COMMIT TRANSACTION;
  220. PRAGMA user_version = 3;
  221. `];
  222. module.exports = new Promise( (resolve, reject) => {
  223. const db = new sqlite3.Database( './wikibot.db', mode, dberror => {
  224. if ( dberror ) {
  225. console.log( '- Error while connecting to the database: ' + dberror );
  226. return reject();
  227. }
  228. db.get( 'PRAGMA user_version;', (error, row) => {
  229. if ( error ) {
  230. console.log( '- Error while getting the database version: ' + error );
  231. return reject();
  232. }
  233. if ( row.user_version > schema.length ) {
  234. console.log( '- Invalid database version: v' + row.user_version );
  235. return reject();
  236. }
  237. if ( row.user_version === schema.length ) {
  238. console.log( '- The database is up to date: v' + row.user_version );
  239. db.close( cerror => {
  240. if ( cerror ) {
  241. console.log( '- Error while closing the database connection: ' + cerror );
  242. return cerror;
  243. }
  244. } );
  245. return resolve();
  246. }
  247. console.log( '- The database outdated: v' + row.user_version );
  248. if ( process.env.READONLY ) return reject();
  249. db.exec( schema.filter( (sql, version) => {
  250. if ( row.user_version === 0 ) return ( version === 0 );
  251. return ( row.user_version <= version );
  252. } ).join('\n'), exerror => {
  253. if ( exerror ) {
  254. console.log( '- Error while updating the database: ' + exerror );
  255. return reject();
  256. }
  257. console.log( '- The database has been updated to: v' + schema.length );
  258. db.close( cerror => {
  259. if ( cerror ) {
  260. console.log( '- Error while closing the database connection: ' + cerror );
  261. return cerror;
  262. }
  263. } );
  264. return resolve();
  265. } );
  266. } );
  267. } );
  268. } );