Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ typings/
# DynamoDB Local files
.dynamodb/

# Jetbrains Configuration
.idea/*
!.idea/codeStyles

# Specific to the tmi.js project

Expand Down
57 changes: 57 additions & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions .idea/codeStyles/codeStyleConfig.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions src/channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ export class Channel {
say(message: string) {
this.client.say(this.toIRC(), message);
}
/**
* Send a whisper to the channel
*/
whisper(message: string) {
this.client.whisper(this, message);
}
}

/**
Expand Down
26 changes: 26 additions & 0 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ export interface Client {
* Received a chat message.
*/
on(event: 'message', listener: (data: ChatMessage) => void): this;
/**
* Received a whisper.
*/
on(event: 'whisper', listener: (data: ChatMessage) => void): this;
/**
* Received a GLOBALUSERSTATE command.
*/
Expand All @@ -92,6 +96,8 @@ export interface Client {
emit(event: 'disconnected', data: DisconnectEvent);
emit(event: 'join', data: JoinEvent);
emit(event: 'part', data: PartEvent);
emit(event: 'message', data: ChatMessage);
emit(event: 'whisper', data: ChatMessage);
emit(event: 'globaluserstate', data: GlobalUserStateEvent);
emit(event: 'roomstate', data: MessageData);
}
Expand Down Expand Up @@ -242,6 +248,10 @@ export class Client extends EventEmitter {
const messageEvent = new ChatMessage(this, data);
this.emit('message', messageEvent);
}
else if (command === 'WHISPER') {
const messageEvent = new ChatMessage(this, data);
this.emit('whisper', messageEvent);
}
else if(command === 'USERSTATE') {
let state: UserState;
if(this.user.states.has(channelName)) {
Expand Down Expand Up @@ -350,6 +360,22 @@ export class Client extends EventEmitter {
});
this.sendRaw(ircMessage);
}
/**
* Send a whisper to a channel on Twitch.
*
* @param {string|Channel} channel Channel to send the whisper message to.
* @param {string} message Whisper message to send.
*/
whisper(channel: string | Channel, message: string) {
if (typeof channel === 'string') {
channel = new Channel(this, channel);
}
//this.sendRaw(`PRIVMSG #jtv :/w ${channel.login} ${message}`);
const ircMessage = tekko.format({
command: 'PRIVMSG', middle: ['#jtv'], trailing: `/w ${channel.login} ${message}`
});
this.sendRaw(ircMessage);
}
/**
* Send a command to a channel on Twitch.
*
Expand Down
13 changes: 11 additions & 2 deletions src/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ export class ChatMessage {
* If the message includes Bits.
*/
isCheer: boolean;
/**
* If the message is a whisper.
*/
isWhisper: boolean;

/**
* @param client A tmi.js Client instance.
Expand All @@ -102,14 +106,19 @@ export class ChatMessage {
this.message = msg.slice(8, -1);
}
this.isCheer = this.tags.has('bits');
this.isWhisper = data.command === 'WHISPER';
this.user = new User(data.prefix.name, this.tags, this.channel);
}
/**
* Send a message back to the same channel that the chat message was sent
* from.
*/
reply(message: string) {
// TODO: Handler whisper replies.
this.channel.say(message);
if (this.isWhisper) {
this.channel.whisper(message);
}
else {
this.channel.say(message);
}
}
}
36 changes: 36 additions & 0 deletions test/channel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const assert = require('assert').strict;
const { describe } = require('mocha');

const tmi = require('../lib/index');

describe('say()', () => {
it('calls client.say()', (done) => {
let client = new tmi.Client();
let channel = new tmi.Channel(client, 'sayChannel');
let message = 'sayMessage';
client.say = (sayChannel, sayMessage) => {
assert.equal(sayChannel, channel.toIRC());
assert.equal(sayMessage, message);
done();
};

// Query result
channel.say(message);
})
});

describe('whisper()', () => {
it('calls client.whisper()', (done) => {
let client = new tmi.Client();
let channel = new tmi.Channel(client, 'whisperChannel');
let message = 'whisperMessage';
client.whisper = (whisperChannel, whisperMessage) => {
assert.equal(whisperChannel, channel);
assert.equal(whisperMessage, message);
done();
};

// Query result
channel.whisper(message);
})
});
59 changes: 59 additions & 0 deletions test/message.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
const assert = require('assert').strict;
const { describe } = require('mocha');

const tmi = require('../lib/index');

describe('reply()', function() {
it('calls channel.whisper() if the message is a whisper', (done) => {
let client = new tmi.Client();
let tags = new tmi.MessageTags();
let trailing = 'replyMessage';
let command = 'WHISPER';
let name = 'replyName';
let prefix = {
name
};
let messageData = {};
let params = [ '#replyChannel' ];
let message = new tmi.ChatMessage(client, {
client, messageData, params, trailing, prefix, tags, command
});
let replyWhisper = 'replyWhisper';
message.channel.whisper = (message) => {
assert.equal(message, replyWhisper);
done();
};
message.channel.say = () => {
done('channel.say() was called when channel.whisper() was expected');
};

// Query result
message.reply(replyWhisper);
});
it('calls channel.say() if the message is not a whisper', (done) => {
let client = new tmi.Client();
let tags = new tmi.MessageTags();
let trailing = 'replyMessage';
let command = 'PRIVMSG';
let name = 'replyName';
let prefix = {
name
};
let messageData = {};
let params = [ '#replyChannel' ];
let message = new tmi.ChatMessage(client, {
client, messageData, params, trailing, prefix, tags, command
});
let replyMessage = 'replyMessage';
message.channel.say = (message) => {
assert.equal(message, replyMessage);
done();
};
message.channel.whisper = () => {
done('channel.whisper() was called when channel.say() was expected');
};

// Query result
message.reply(replyMessage);
});
});