UNPKG

4.46 kBJavaScriptView Raw
1const yaml = require('js-yaml')
2const fs = require('fs-extra')
3const { Collection } = require('discord.js')
4const path = require('path')
5const { getThread } = require('./messenger')
6const Connection = require('./Connection')
7
8class ConnectionsManager {
9 constructor () {
10 const connectionsPath = path.join(config.path, 'connections.yml')
11 const channelsPath = path.join(config.path, 'channels.yml')
12 if (fs.existsSync(channelsPath) && !fs.existsSync(connectionsPath)) {
13 fs.copyFileSync(channelsPath, connectionsPath)
14 }
15
16 this.path = connectionsPath
17 }
18
19 init () {
20 this.list = new Collection()
21 return this.save()
22 }
23
24 async load () {
25 const log = logger.withScope('CM:init')
26 try {
27 // load file and parse YAML
28 let parsed = yaml.safeLoad(fs.readFileSync(this.path, 'utf8'))
29
30 if (!parsed || typeof parsed !== 'object') return this.init()
31
32 // create Collection from these channels
33 this.list = new Collection()
34 await Promise.all(Object.entries(parsed).map(async ([name, endpoints]) => {
35 log.trace(name, endpoints)
36 if (typeof endpoints === 'string' || endpoints.some(el => typeof el === 'string')) return this.parseOldFormat(name, endpoints)
37 endpoints = await Promise.all(endpoints.map(async endpoint => {
38 if (!endpoint.type || !endpoint.id) throw new Error('type or id missing on endpoint ' + JSON.stringify(endpoint))
39 if (endpoint.name) return endpoint
40 endpoint.name = endpoint.type === 'discord'
41 ? discord.client.channels.get(endpoint.id).name
42 : (await getThread(endpoint.id)).name
43 return endpoint
44 }))
45 this.list.set(name, new Connection(name, endpoints))
46 }))
47 await this.save()
48 } catch (err) {
49 if (err.code !== 'ENOENT') throw err
50 await this.init()
51 }
52 }
53
54 async parseOldFormat (key, value) {
55 const log = logger.withScope('CM:parseOldFormat')
56 if (key.startsWith('_') || value === '0') return log.debug(`Ignoring ${key}`)
57
58 let name = discord.client.channels.get(key).name
59
60 const connection = new Connection(name).addChannel({ id: key, name })
61 if (typeof value === 'string') {
62 connection.addThread({ id: value, name: (await getThread(value)).name })
63 } else {
64 for (let threadID of value) {
65 connection.addThread({ id: threadID, name: (await getThread(threadID)).name })
66 }
67 }
68
69 log.debug('migrated connection', connection)
70 await connection.save()
71 }
72
73 async createAutomaticDiscordChannel (threadID, name) {
74 const log = logger.withScope('CM:createAutomaticDiscordChannel')
75
76 // create new channel with specified name and set its parent
77 const channel = await discord.guilds[0].createChannel(name, 'text')
78 await channel.overwritePermissions(discord.guilds[0].roles.find(role => role.name === '@everyone').id, { VIEW_CHANNEL: false })
79 log.debug(`Channel created, name: ${name}, id: ${channel.id}`)
80
81 // set category if it's in the same guild
82 if (discord.category && discord.category.guild.id === channel.guild.id) await channel.setParent(discord.category)
83
84 // save newly created channel in the channels map
85 const connection = new Connection(name)
86 .addChannel({ id: channel.id, name })
87 .addThread({ id: threadID.toString(), name })
88 await connection.save()
89
90 log.trace('new connection', connection, 1)
91 return connection
92 }
93
94 async getWithCreateFallback (threadID, name) {
95 const log = logger.withScope('CM:getWithCreateFallback')
96 let connection = connections.getWith(threadID)
97 if (!connection) {
98 if (!config.discord.createChannels) return log.debug(`Channel creation disabled, ignoring. Name: ${name}, id: ${threadID}`)
99 connection = await connections.createAutomaticDiscordChannel(threadID, name)
100 }
101 return connection
102 }
103
104 getWith (id) {
105 return this.list.find(connection => connection.has(id))
106 }
107
108 get (name) {
109 return this.list.get(name)
110 }
111
112 has (id) {
113 return this.list.some(connection => connection.has(id))
114 }
115
116 save () {
117 let obj = {
118 __comment: 'This is your connections.yml file. More info at https://github.com/miscord/miscord/wiki/Connections.yml'
119 }
120 if (this.list.size) {
121 obj = Object.assign(obj, ...this.list.map(connection => connection.toObject()))
122 }
123 return fs.writeFile(this.path, yaml.safeDump(obj), 'utf8')
124 }
125}
126
127module.exports = ConnectionsManager