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.

175 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. }
  63. let connectWithPassword = (err, data) => {
  64. if (err === null) {
  65. logger.info("Successfully authenticated with password %o", data);
  66. startServerConnection();
  67. } else {
  68. logger.error("Failed to authenticate with password %o", err);
  69. }
  70. }
  71. let connectWithToken = (err, data) => {
  72. if (err === null) {
  73. logger.info("Successfully authenticated with access token %o", data);
  74. startServerConnection();
  75. } else {
  76. logger.error("Failed to authenticate with access token %o", err);
  77. if (typeof botConfig.userPassword !== 'undefined') {
  78. botClient.loginWithPassword(botConfig.userId, botConfig.userPassword, connectWithPassword);
  79. } else {
  80. logger.error("No fallback password provided!");
  81. }
  82. }
  83. }
  84. logger.info("Authenticating With Server");
  85. botClient.loginWithToken(this.config.accessToken, connectWithToken);
  86. }
  87. updateAvatar(avatarFile, overwrite = false) {
  88. let matrixClient = this.client;
  89. let botConfig = this.config;
  90. let promises = [Promise.resolve(true)];
  91. if (this.connected) {
  92. promises.push(this.client.getProfileInfo(this.config.userId, "avatar_url")
  93. .then((existingAvatarUrl) => {
  94. logger.info("Recieved avatar_url: %o", existingAvatarUrl);
  95. if (typeof existingAvatarUrl !== 'undefined' && typeof existingAvatarUrl == 'object'
  96. && existingAvatarUrl.constructor === Object && Object.keys(existingAvatarUrl).length !== 0
  97. && !overwrite) {
  98. logger.info("Avatar already set");
  99. } else {
  100. logger.info("Setting avatar content from %s", avatarFile);
  101. let avatarFileBuffer = fs.readFileSync(avatarFile);
  102. logger.debug("Avatar Image Data %o", avatarFileBuffer);
  103. matrixClient.uploadContent(avatarFileBuffer, {
  104. name: botConfig.userId + " avatar",
  105. type: "image/jpeg",
  106. rawResponse: false
  107. }).then((uploadedAvatar) => {
  108. logger.info("Uploaded avatar %o", uploadedAvatar);
  109. matrixClient.setAvatarUrl(uploadedAvatar.content_uri)
  110. .then(() => {
  111. logger.info("Updated %s avatar to %s", botConfig.userId, uploadedAvatar.content_uri);
  112. return true;
  113. });
  114. });
  115. }
  116. }));
  117. } else {
  118. logger.warn("Attempting to update avatar while disconnected");
  119. }
  120. return Promise.all(promises);
  121. }
  122. sendStatusStartup() {
  123. let promises = [Promise.resolve(true)]
  124. if (this.connected) {
  125. this.config.statusRooms.forEach(roomId => {
  126. logger.debug("Notifying %s of startup", roomId);
  127. promises.push(this.client.sendMessage(
  128. roomId, message.createBasic("Started with version: " + this.buildInfo, message.types.NOTICE)
  129. ).then(() => {
  130. logger.debug("Notified %s of startup", roomId);
  131. }));
  132. });
  133. } else {
  134. logger.warn("Attempting to send startup message while disconnected");
  135. }
  136. return Promise.all(promises);
  137. }
  138. sendStatusShutdown() {
  139. let promises = [Promise.resolve(true)]
  140. if (this.connected) {
  141. this.config.statusRooms.forEach(roomId => {
  142. logger.debug("Notifying %s of shutdown", roomId);
  143. promises.push(this.client.sendMessage(
  144. roomId, message.createBasic("Shutting down", message.types.NOTICE)
  145. ).then(() => {
  146. logger.debug("Notified %s of shutdown", roomId);
  147. }));
  148. });
  149. } else {
  150. logger.warn("Attempting to send shutdown message while disconnected");
  151. }
  152. return Promise.all(promises);
  153. }
  154. }
  155. function create(config) {
  156. let buildInfo = utility.getBuildInfo();
  157. logger.info("Running version: %s", buildInfo);
  158. return new Bot(config, buildInfo);
  159. }
  160. exports.create = create;