Baphomet is the dedicated bot for nulloctet matrix
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
6.7 KiB

  1. let fs = require('fs');
  2. let sdk = require('matrix-js-sdk');
  3. let message = require('./message');
  4. let utility = require('./utility');
  5. let { logger } = require('./logging');
  6. class Bot {
  7. constructor(config, buildInfo) {
  8. this.config = config;
  9. this.buildInfo = buildInfo;
  10. this.connected = false;
  11. }
  12. /**
  13. * Initialize the bot connection
  14. */
  15. init(messageCallback) {
  16. logger.info("Creating Matrix Client")
  17. this.client = sdk.createClient({
  18. baseUrl: this.config.baseUrl,
  19. userId: this.config.userId
  20. });
  21. this.client.on("sync", async (state, previousState, data) => {
  22. switch (state) {
  23. case "PREPARED":
  24. this.connected = true;
  25. await this.sendStatusStartup();
  26. await this.updateAvatar(process.env.NODE_PATH + '/assets/avatar.jpg');
  27. this.client.getJoinedRooms()
  28. .done((rooms) => {
  29. logger.info("Connected to: %o", rooms)
  30. });
  31. break;
  32. case "SYNCING":
  33. logger.debug("Syncing")
  34. break;
  35. case "RECONNECTING":
  36. logger.debug("Reconnecting");
  37. break;
  38. default:
  39. logger.error("Unexpected sync state: %s", state);
  40. process.exit(1);
  41. }
  42. });
  43. this.client.on("RoomMember.membership", (event, member) => {
  44. if (member.membership === "invite"
  45. && this.config.admin.indexOf(ember.userId) >= 0) {
  46. this.client.joinRoom(member.roomId).done(() => {
  47. logger.info("Auto-joined %s", member.roomId);
  48. });
  49. }
  50. });
  51. this.client.on("Room.timeline", messageCallback);
  52. return this;
  53. }
  54. async connect() {
  55. // logger.info("Initializing Crypto");
  56. // await bot.client.initCrypto();
  57. let botClient = this.client;
  58. let botConfig = this.config;
  59. let startServerConnection = async () => {
  60. logger.info("Starting Matrix SDK Client");
  61. await this.client.startClient({
  62. initialSyncLimit: 0
  63. });
  64. }
  65. let connectWithPassword = (err, data) => {
  66. if (err === null) {
  67. logger.info("Successfully authenticated with password %o", data);
  68. startServerConnection();
  69. } else {
  70. logger.error("Failed to authenticate with password %o", err);
  71. }
  72. }
  73. let connectWithToken = (err, data) => {
  74. if (err === null) {
  75. logger.info("Successfully authenticated with access token %o", data);
  76. startServerConnection();
  77. } else {
  78. logger.error("Failed to authenticate with access token %o", err);
  79. if (typeof botConfig.userPassword !== 'undefined') {
  80. botClient.loginWithPassword(botConfig.userId, botConfig.userPassword, connectWithPassword);
  81. } else {
  82. logger.error("No fallback password provided!");
  83. }
  84. }
  85. }
  86. logger.info("Authenticating With Server");
  87. botClient.loginWithToken(this.config.accessToken, connectWithToken);
  88. }
  89. updateAvatar(avatarFile, overwrite = false) {
  90. let matrixClient = this.client;
  91. let botConfig = this.config;
  92. let promises = [Promise.resolve(true)];
  93. if (this.connected) {
  94. promises.push(this.client.getProfileInfo(this.config.userId, "avatar_url")
  95. .then((existingAvatarUrl) => {
  96. logger.info("Recieved avatar_url: %o", existingAvatarUrl);
  97. if (typeof existingAvatarUrl !== 'undefined' && typeof existingAvatarUrl == 'object'
  98. && existingAvatarUrl.constructor === Object && Object.keys(existingAvatarUrl).length !== 0
  99. && !overwrite) {
  100. logger.info("Avatar already set");
  101. } else {
  102. logger.info("Setting avatar content from %s", avatarFile);
  103. let avatarFileBuffer = fs.readFileSync(avatarFile);
  104. logger.debug("Avatar Image Data %o", avatarFileBuffer);
  105. matrixClient.uploadContent(avatarFileBuffer, {
  106. name: botConfig.userId + " avatar",
  107. type: "image/jpeg",
  108. rawResponse: false
  109. }).then((uploadedAvatar) => {
  110. logger.info("Uploaded avatar %o", uploadedAvatar);
  111. matrixClient.setAvatarUrl(uploadedAvatar.content_uri)
  112. .then(() => {
  113. logger.info("Updated %s avatar to %s", botConfig.userId, uploadedAvatar.content_uri);
  114. return true;
  115. });
  116. });
  117. }
  118. }));
  119. } else {
  120. logger.warn("Attempting to update avatar while disconnected");
  121. }
  122. return Promise.all(promises);
  123. }
  124. sendStatusStartup() {
  125. let promises = [Promise.resolve(true)]
  126. if (this.connected) {
  127. this.config.statusRooms.forEach(roomId => {
  128. logger.debug("Notifying %s of startup", roomId);
  129. promises.push(this.client.sendMessage(
  130. roomId, message.createBasic("Started with version: " + this.buildInfo, message.types.NOTICE)
  131. ).then(() => {
  132. logger.debug("Notified %s of startup", roomId);
  133. }));
  134. });
  135. } else {
  136. logger.warn("Attempting to send startup message while disconnected");
  137. }
  138. return Promise.all(promises);
  139. }
  140. sendStatusShutdown() {
  141. let promises = [Promise.resolve(true)]
  142. if (this.connected) {
  143. this.config.statusRooms.forEach(roomId => {
  144. logger.debug("Notifying %s of shutdown", roomId);
  145. promises.push(this.client.sendMessage(
  146. roomId, message.createBasic("Shutting down", message.types.NOTICE)
  147. ).then(() => {
  148. logger.debug("Notified %s of shutdown", roomId);
  149. }));
  150. });
  151. } else {
  152. logger.warn("Attempting to send shutdown message while disconnected");
  153. }
  154. return Promise.all(promises);
  155. }
  156. }
  157. function create(config) {
  158. let buildInfo = utility.getBuildInfo();
  159. logger.info("Running version: %s", buildInfo);
  160. return new Bot(config, buildInfo);
  161. }
  162. exports.create = create;