lowdb_migrator.ts 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. import { existsSync, readFileSync, renameSync } from "fs";
  2. import { ReactionType, ReactionEmote } from "./entity/ReactionEmote";
  3. import { getRepository, Repository } from "typeorm";
  4. import { KnownUser, User, UserRole } from "./entity/KnownUser";
  5. import { Dictionary } from "lodash";
  6. import { Guide, GuideKeyword, GuideType } from "./entity/Guide";
  7. import { Quote } from "./entity/Quote";
  8. import { MessageReaction } from "./entity/MessageReaction";
  9. import { FaceCaptionMessage, FaceCaptionType } from "./entity/FaceCaptionMessage";
  10. import { PostedForumNewsItem } from "./entity/PostedForumsNewsItem";
  11. import { KnownChannel } from "./entity/KnownChannel";
  12. import { DeadChatReply } from "./entity/DeadChatReply";
  13. type EmoteTable = { [reactionType: string]: string[] };
  14. interface IGuide {
  15. name: string;
  16. displayName: string;
  17. content: string;
  18. }
  19. interface IEditors {
  20. roles: string[];
  21. users: string[];
  22. }
  23. interface INewsItem {
  24. hash: string;
  25. messageId: string;
  26. }
  27. interface IQuote {
  28. author: string;
  29. message: string;
  30. }
  31. interface IFaceCaptionTable {
  32. pre: string[];
  33. post: string[];
  34. }
  35. type NewsTable = { [id: string] : INewsItem | boolean};
  36. type MessageReactionsTable = { [message: string] : string };
  37. type FaceEditProbabilityTable = { [channel: string] : number };
  38. interface IOldDatabase {
  39. emotes: EmoteTable;
  40. reactableMentionedUsers: string[];
  41. specialUsers: string[];
  42. bigUsers: string[];
  43. dedUsers: string[];
  44. editors: IEditors;
  45. memes: IGuide[];
  46. miscs: IGuide[];
  47. guides: IGuide[];
  48. quotes: IQuote[];
  49. messageReactions: MessageReactionsTable;
  50. faceCaptions: IFaceCaptionTable;
  51. postedNewsGuids: NewsTable;
  52. faceEditChannels: FaceEditProbabilityTable;
  53. deadChatReplies: string[];
  54. newsPostVerifyChannel: string;
  55. feedOutputChannel: string;
  56. aggregateChannel: string;
  57. latestKissDiaryEntry: number;
  58. latestCom3D2WorldDiaryEntry: number;
  59. lastCOMJPVersion: number;
  60. }
  61. async function migrateEmotes(db: IOldDatabase) {
  62. let repo = getRepository(ReactionEmote);
  63. for (const emoteType in db.emotes) {
  64. if(!Object.values(ReactionType).includes(emoteType)) {
  65. console.log(`WARN: emote type ${emoteType} is not a predefined emote type!`)
  66. continue;
  67. }
  68. await repo.save(db.emotes[emoteType].map(id => repo.create({
  69. reactionId: id,
  70. type: emoteType as ReactionType
  71. })));
  72. }
  73. }
  74. async function migrateUsers(db: IOldDatabase) {
  75. let userRepo = getRepository(User);
  76. let roleRepo = getRepository(UserRole);
  77. let users : Dictionary<User> = {};
  78. let roles : Dictionary<UserRole> = {};
  79. let iterator = <T extends KnownUser>(targetDict : Dictionary<T>, repo: Repository<T>, ids: string[], action: (u: T) => void) => {
  80. for(let userId of ids) {
  81. let u : T;
  82. if(userId in users)
  83. u = targetDict[userId];
  84. else{
  85. u = targetDict[userId] = repo.create();
  86. u.userID = userId;
  87. }
  88. action(u);
  89. }
  90. };
  91. iterator(users, userRepo, db.reactableMentionedUsers, u => u.mentionReactionType = ReactionType.ANGERY);
  92. iterator(users, userRepo, db.specialUsers, u => u.replyReactionType = ReactionType.HUG);
  93. iterator(users, userRepo, db.bigUsers, u => u.replyReactionType = ReactionType.BIG);
  94. iterator(users, userRepo, db.dedUsers, u => u.replyReactionType = ReactionType.DED);
  95. iterator(users, userRepo, db.editors.users, u => u.canModerate = true);
  96. iterator(roles, roleRepo, db.editors.roles, r => r.canModerate = true);
  97. await userRepo.save(Object.values(users));
  98. await roleRepo.save(Object.values(roles));
  99. }
  100. async function migrateGuides(db : IOldDatabase) {
  101. let guideRepo = getRepository(Guide);
  102. let keywordsRepo = getRepository(GuideKeyword);
  103. let keywords : Dictionary<GuideKeyword> = {};
  104. let dbGuides : Guide[] = [];
  105. let process = async (guides: IGuide[], type: GuideType) => {
  106. for(let guide of guides){
  107. if(!guide.displayName)
  108. continue;
  109. let guideKeywords = guide.name.split(" ").map(s => s.trim().toLowerCase());
  110. let keywordsObjects : GuideKeyword[] = [];
  111. for(let keyword of guideKeywords) {
  112. let keywordObj : GuideKeyword;
  113. if(keyword in keywords)
  114. keywordObj = keywords[keyword];
  115. else
  116. keywordObj = keywords[keyword] = await keywordsRepo.save(keywordsRepo.create({ keyword: keyword }));
  117. keywordsObjects.push(keywordObj);
  118. }
  119. let guideObj = guideRepo.create({
  120. keywords: keywordsObjects,
  121. type: type,
  122. displayName: guide.displayName,
  123. content: guide.content
  124. });
  125. dbGuides.push(guideObj);
  126. }
  127. };
  128. await process(db.memes, GuideType.MEME);
  129. await process(db.guides, GuideType.GUIDE);
  130. await process(db.miscs, GuideType.MISC);
  131. // await keywordsRepo.save(Object.values(keywords));
  132. await guideRepo.save(dbGuides);
  133. }
  134. async function migrateQuotes(db: IOldDatabase) {
  135. let repo = getRepository(Quote);
  136. await repo.save(db.quotes.map(q => repo.create({
  137. author: q.author,
  138. message: q.message
  139. })));
  140. }
  141. async function migrateMessageReactions(db: IOldDatabase) {
  142. let repo = getRepository(MessageReaction);
  143. await repo.save(Object.entries(db.messageReactions).map(([message, emoteId]) => repo.create({
  144. message: message,
  145. reactionEmoteId: emoteId
  146. })));
  147. }
  148. async function migrateFaceCaptions(db: IOldDatabase) {
  149. let repo = getRepository(FaceCaptionMessage);
  150. await repo.save([
  151. ...db.faceCaptions.pre.map(s => repo.create( {
  152. message: s,
  153. type: FaceCaptionType.PREFIX
  154. })),
  155. ...db.faceCaptions.post.map(s => repo.create( {
  156. message: s,
  157. type: FaceCaptionType.POSTFIX
  158. }))
  159. ]);
  160. }
  161. async function migrateNews(db: IOldDatabase) {
  162. let repo = getRepository(PostedForumNewsItem);
  163. await repo.save(Object.entries(db.postedNewsGuids).filter(([id, item]) => typeof item != "boolean").map(([id, item]) => repo.create({
  164. hash: (item as INewsItem).hash,
  165. postedMessageId: (item as INewsItem).messageId,
  166. id: id
  167. })));
  168. }
  169. async function migrateChannels(db: IOldDatabase) {
  170. let repo = getRepository(KnownChannel);
  171. await repo.save([
  172. repo.create({
  173. channelId: db.newsPostVerifyChannel,
  174. channelType: "newsPostVerify"
  175. }),
  176. repo.create({
  177. channelId: db.aggregateChannel,
  178. channelType: "aggregatorManager"
  179. }),
  180. repo.create({
  181. channelId: db.feedOutputChannel,
  182. channelType: "newsFeed"
  183. }),
  184. ...Object.entries(db.faceEditChannels).map(([channelId, prob]) => repo.create({
  185. channelId: channelId,
  186. faceMorphProbability: prob
  187. }))
  188. ]);
  189. }
  190. async function migrateDeadMessages(db: IOldDatabase) {
  191. let repo = getRepository(DeadChatReply);
  192. await repo.save(db.deadChatReplies.map(r => repo.create({
  193. message: r
  194. })));
  195. }
  196. export async function migrate() {
  197. if(!existsSync("./db.json"))
  198. return;
  199. let json = readFileSync("./db.json", { encoding: "utf-8" });
  200. let db = JSON.parse(json) as IOldDatabase;
  201. await migrateEmotes(db);
  202. await migrateUsers(db);
  203. await migrateGuides(db);
  204. await migrateQuotes(db);
  205. await migrateMessageReactions(db);
  206. await migrateFaceCaptions(db);
  207. await migrateNews(db);
  208. await migrateChannels(db);
  209. await migrateDeadMessages(db);
  210. renameSync("./db.json", "./db_migrated.json");
  211. }