twitch-chat.js
Version:
A simple twitch API wrapper
159 lines (146 loc) • 4.69 kB
JavaScript
const WS = require('ws');
const msg = require('../../util/_.js');
const Message = require('../structures/Message.js');
const Author = require('../structures/Author.js');
const UserStream = require('../structures/UserChannel.js');
const ClientUser = require('../structures/ClientUser.js');
const {parseMessage} = require('../../util/parser.js');
module.exports = class WebSocket {
constructor(twitch) {
this.twitch = twitch
this.ws = null
this.l = -1
this.connection = false
this.msg = msg
}
async userinfo_update() {
let s = await this.twitch.fetch.LOGin(this.twitch.options.client_name)
this.twitch.user = new ClientUser(this.twitch, s)
process.env.ID = this.twitch.user.id
}
debug(message) {
return this.twitch.emit('debug', message)
}
join_channels() {
let channels = this.twitch.options.channels
if(!channels) return;
this.twitch.user.join({add: false}, channels)
}
async handleMessage(data, d) {
let user;
let channel;
let message;
switch(data?.command.command) {
case 'CLEARCHAT':
if(data.tags['ban-duration']) {
let user = await this.twitch.users.fetch(data.tags['target-user-id'])
let to = {
type: 'timeout',
timeout_duration: data.tags['ban-duration'],
room_id: data.tags['room-id'],
target: user,
timeCreatedTimestamp: data.tags['tmi-sent-ts']
}
this.twitch.emit('punishment', to)
}
break;
case 'JOIN':
setTimeout(async() => {
user = await this.twitch.users.fetch(data.source.nick)
channel = await this.twitch.channels.fetch(data.command.channel)
this.twitch.emit('joined', user, channel)
}, 900)
break;
case 'PART':
setTimeout(async() => {
user = await this.twitch.users.fetch(data.source.nick)
channel = await this.twitch.channels.fetch(data.command.channel)
this.twitch.emit('left', user, channel)
}, 900)
break;
case 'ROOMSTATE':
this.twitch.emit('state', {type: 'room', room: data.tags})
break;
case 'USERSTATE':
this.twitch.emit('state', {type: 'user', user: data.tags})
break;
case "PRIVMSG":
channel = await this.twitch.channels.fetch(data.command.channel)
user = await this.twitch.users.fetch(data.source.nick)
let data_ = await this.twitch.fetch.LOGin(user.login_name)
message = new Message(data)
channel.type = 'live'
message.channel = channel
message.channel.stream.user = new UserStream(this.twitch, data_, message.channel)
message.author = new Author(data.tags, user)
this.twitch.emit('message', message)
break;
}
let p = this.msg.msg(d)
if(!p.isWhisper) return;
channel = await this.twitch.channels.fetch(p['display-name'])
let message_ = new Message(p)
channel.type = 'whisper'
message_.channel = channel
message_.author = new Author(p, message_.channel.user)
this.twitch.emit('message', message_)
}
async messages_ws(msg_) {
let json = this.msg.json_messages(msg_)
if(json.command === 'PONG') {
this.twitch.ping = Date.now() - this.l
this.debug(`Responded with latency: ${this.twitch.ping}ms`)
await this.userinfo_update()
}
if(json.command === 'PING') {
this.debug('Responded with PING. Sent PONG')
this.ws.send('PONG')
}
json.ok?this.debug(`Status recived: ${json.ok}`):''
if(json.ok === 376) {
setInterval(() => {
this.l = Date.now()
this.debug('Got 376')
this.debug('Sending heartbeat (60 seconds)')
this.ws.send('PING')
}, 60000)
}
}
async connect() {
this.l = Date.now()
this.twitch.ws = new WS('wss://irc-ws.chat.twitch.tv:443/', 'irc')
this.ws = this.twitch.ws
this.debug('Connecting to the server...')
this.ws.onmessage = await this._onMessage.bind(this)
this.ws.onopen = this._onOpen.bind(this)
}
async _onMessage(e) {
let data = e.data.trim().split('\r\n')
let message = e.data.trimEnd().split('\r\n')
message.forEach(msg => {
let parsedMessage = parseMessage(msg);
this.handleMessage(parsedMessage, data)
})
let arr = [];
data.forEach(mg => {
arr.push(mg)
})
await this.messages_ws(arr)
}
async _onOpen() {
this.debug('Sending PASS')
this.debug('Sending CAP')
this.debug('Sending NICK')
this.ws.send(`CAP REQ :twitch.tv/tags twitch.tv/commands twitch.tv/membership`);
this.ws.send(`PASS oauth:${process.env.CLIENT_TOKEN}`)
this.ws.send(`NICK ${this.twitch.options.name}`)
this.debug('-------------------')
this.debug(' CAP: OK\n PASS: OK\n NICK: OK')
this.debug('-------------------')
this.twitch.ping = Date.now() - this.l
await this.userinfo_update()
this.join_channels()
this.connection = true
this.twitch.emit('ready', this.twitch)
}
}