emote.js 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. const _ = require('lodash')
  2. const Mutex = require('promise-mutex')
  3. const MAX_EMOTES_IN_GUILD = 50
  4. class EmoteStore {
  5. constructor(game, guildIDs) {
  6. this.game = game
  7. this.guildIDs = guildIDs
  8. this.emotes = new Map() // id -> Emoji
  9. this.mutex = new Mutex()
  10. this.game.log.info(`Emote store capacity = ${this.guildIDs.length * MAX_EMOTES_IN_GUILD}`)
  11. if (this.guildIDs.length === 0) {
  12. throw 'Need at least one emote store server'
  13. }
  14. }
  15. randomClient() {
  16. return _.sample(this.game.clientPool)
  17. }
  18. // Cleans up each emote-storage guild, by removing all channels and emotes
  19. // present there. RIP.
  20. async cleanUp() {
  21. await Promise.all(this.guildIDs.map(guildID => {
  22. const guild = this.randomClient().guilds.get(guildID)
  23. return Promise.all([
  24. ...guild.channels.map(c => c.delete()),
  25. ...guild.emojis.map(e => guild.deleteEmoji(e)),
  26. ])
  27. }))
  28. }
  29. // Finds a guild with emote slots available. If there are none, deletes an
  30. // old emote from a guild.
  31. async findGuildForNewEmote(makeSlots = false) {
  32. for (const guildID of _.shuffle(this.guildIDs)) {
  33. const guild = this.randomClient().guilds.get(guildID)
  34. if (guild.emojis.size === MAX_EMOTES_IN_GUILD) {
  35. // Full, make a slot
  36. if (makeSlots) {
  37. const emoteToDel = guild.emojis.random()
  38. this.emotes.delete(emoteToDel.name)
  39. await guild.deleteEmoji(emoteToDel)
  40. }
  41. } else {
  42. // Has slots, use it
  43. return guild
  44. }
  45. }
  46. return this.findGuildForNewEmote(true) // Make slots this time
  47. }
  48. // Gets an emote by name, uploading it if it isn't found. Returns an Emoji.
  49. async get(name, graphic) {
  50. // Don't upload it if it's already there.
  51. if (this.emotes.has(name)) {
  52. return this.emotes.get(name)
  53. }
  54. // Upload it.
  55. let emote
  56. await this.mutex.lock(async () => {
  57. const guild = await this.findGuildForNewEmote()
  58. emote = await guild.createEmoji(graphic, name)
  59. })
  60. this.emotes.set(name, emote)
  61. return emote
  62. }
  63. }
  64. module.exports = EmoteStore