Permalink
Browse files

Week 15, user badges.

  • Loading branch information...
roncli committed Aug 1, 2017
1 parent 31bd6b9 commit 8f547865a3a6b0914c8244c9afce227d4c64a032
Showing with 160 additions and 28 deletions.
  1. +0 −1 app/package.json
  2. +8 −0 app/site/css/index.css
  3. +0 −1 app/site/index.htm
  4. +86 −23 app/site/js/index.js
  5. +66 −3 app/site/modules/chat/twitch/index.js
@@ -20,7 +20,6 @@
"dependencies": {
"bootstrap": "3.3.7",
"bootstrap-colorpicker": "2.5.1",
"emojionearea": "3.1.5",
"express": "4.15.3",
"iconv-lite": "0.4.18",
"jquery": "3.2.1",
@@ -43,6 +43,12 @@ body {
word-wrap: break-word;
}

#display > .tab-pane > .chat > .text img.twitch-badge,
#display > .tab-pane > .users img.twitch-badge {
height: 18px;
padding-right: 3px;
}

#display > .tab-pane > .chat > .text img.emote {
height: 28px;
}
@@ -113,6 +119,8 @@ body {
flex-shrink: 0;
min-width: 75px;
max-width: 250px;
padding-left: 2px;
padding-right: 2px;
}

#input {
@@ -4,7 +4,6 @@
<script>$ = jQuery = require("jquery")</script>
<script src="../node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="js/index.js"></script>
<script src="../node_modules/emojionearea/dist/emojionearea.js"></script>
<link href="../node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"></link>
<link href="../node_modules/bootstrap/dist/css/bootstrap-theme.min.css" rel="stylesheet"></link>
<link href="css/index.css" rel="stylesheet"></link>
@@ -127,27 +127,79 @@ class Index {
if (!channels[channel]) {
return;
}

client.getStream(channelName).then((stream) => {
if (stream) {
channels[channel].stream = stream;
channels[channel].channel = stream.channel;
Index.updateTitle(channel);
} else {
delete channels[channel].stream;
client.getChannel(channelName).then((channelData) => {
channels[channel].channel = channelData;
return new Promise((resolve, reject) => {
if (stream) {
channels[channel].stream = stream;
channels[channel].channel = stream.channel;
Index.updateTitle(channel);
resolve();
} else {
delete channels[channel].stream;
client.getChannel(channelName).then((channelData) => {
channels[channel].channel = channelData;
Index.updateTitle(channel);
resolve();
}).catch(reject);
}
});
}).then(() => {
if (!channels[channel].badges) {
client.getChannelBadges(channels[channel].channel._id).then((badges) => {
channels[channel].badges = badges;
});
}
});

Index.listUsers(channel);
}

// ## # # # #
// # # # #
// # ## ### ### # # ### ## ### ###
// # # ## # # # ## # ## # # ##
// # # ## # # # ## ## # ##
// ### ### ### ## ## ### ## # ###
static listUsers(channel) {
var channelName = channel.substring(1);

client.getChatters(channelName).then((chatters) => {
channels[channel].chatters = chatters;
Index.updateTitle(channel);

Index.displayUsers(channel);
});
}

// # # ## # #
// # # # #
// ### ## ### ### # ### # # # # ### ## ### ###
// # # # ## # # # # # # # # # ## # ## # # ##
// # # # ## # # # # ## # # # # ## ## # ##
// ### ### ### ### ### # # # ## ### ## # ###
// # #
static displayUsers(channel) {
const channelName = channel.substring(1),
users = [];

if (!channels[channel].chatters) {
return;
}

Object.keys(channels[channel].chatters.chatters).forEach((key) => {
channels[channel].chatters.chatters[key].forEach((user) => {
users.push(user);
});
});

$(`#channel-${channelName} .users`).html(
users.map((username) => {
return `${channels[channel].userBadges[username] || ""}${username}`;
}).join("<br />")
);
}

// # # ### # # ##
// # # # # #
// # # ### ### ### ### ## # ## ### # ##
@@ -237,12 +289,13 @@ win.data.appSettings = new File(path.join(app.getPath("userData"), "appSettings.
// # # # ## # # # ## # # # # # # # ## ## ## # ## ## ## #
// ## ### ### ## # # ## ## ## # # # # # ## ### ### # # # ## #
// ###
client.on("message", (channel, username, usercolor, displayname, html, text) => {
client.on("message", (channel, username, usercolor, displayname, badges, html, text) => {
var color = tinycolor(usercolor),
background = tinycolor(win.data.appSettings.data.chat.colors.chat.background),
brightness = background.getBrightness(),
difference = brightness - color.getBrightness(),
channelName = channel.substring(1);
channelName = channel.substring(1),
badgeHtml = "";

if (difference > 0 && difference < 50) {
usercolor = color.darken(50);
@@ -256,11 +309,27 @@ client.on("message", (channel, username, usercolor, displayname, html, text) =>
}
}

if (badges) {
Object.keys(badges).forEach((key) => {
const {[key]: version} = badges,
badge = channels[channel].badges[key].versions[version];

badgeHtml += $("<img></img>").attr({
src: badge.image_url_1x,
title: badge.title
}).addClass("twitch-badge")[0].outerHTML;
});

channels[channel].userBadges[username] = badgeHtml;
}

if ($("<div></div>").append(html).text().indexOf(win.data.userSettings.data.twitch.username) === -1) {
Index.appendToChannel($(`#channel-${channelName} .text`), `<span class="user-${username}">${Index.timestamp()}<b style="color: ${usercolor}">${Index.userLink(channel, username, displayname)}</b>: ${html}</span>`);
Index.appendToChannel($(`#channel-${channelName} .text`), `<span class="user-${username}">${Index.timestamp()}${badgeHtml}<b style="color: ${usercolor}">${Index.userLink(channel, username, displayname)}</b>: ${html}</span>`);
} else {
Index.appendToChannel($(`#channel-${channelName} .text`), `<span class="user-${username}">${Index.timestamp()}<b style="color: ${usercolor}">${Index.userLink(channel, username, displayname)}</b>: <span class="highlight">${html}</span></span>`);
Index.appendToChannel($(`#channel-${channelName} .text`), `<span class="user-${username}">${Index.timestamp()}${badgeHtml}<b style="color: ${usercolor}">${Index.userLink(channel, username, displayname)}</b>: <span class="highlight">${html}</span></span>`);
}

Index.displayUsers(channel);
});

// ## # # # # # # # # # #
@@ -274,9 +343,9 @@ client.on("join", (channel, username, self) => {
var channelName = channel.substring(1);
if (self) {
channels[channel] = {
users: [],
interval: setInterval(() => Index.updateStream(channel), 60000),
isAtBottom: true
isAtBottom: true,
userBadges: {}
};
$("#channels").append(Index.getTab(channelName));
$("#display").append(Index.getPanel(channelName));
@@ -285,9 +354,8 @@ client.on("join", (channel, username, self) => {
}
Index.updateStream(channel);
}
channels[channel].users.push(username);
Index.appendToChannel($(`#channel-${channelName} .text`), `<span class="join">${Index.timestamp()}${(self ? "You have" : `${Index.userLink(channel, username)} has`)} joined ${channel}</span>`);
$(`#channel-${channelName} .users`).html(channels[channel].users.join("<br />"));
Index.displayUsers(channel);
});

// ## # # # # # # # # #
@@ -309,9 +377,8 @@ client.on("part", (channel, username, self) => {
$(`.channel-tab:nth-child(${index === Object.keys(channels).length ? index : index + 1}) > a`).tab("show");
}
} else {
channels[channel].users.splice(channels[channel].users.indexOf(username), 1);
Index.appendToChannel($(`#channel-${channelName} .text`), `<span class="part">${Index.timestamp()}${`${Index.userLink(channel, username)}`} has left ${channel}</span>`);
$(`#channel-${channelName} .users`).html(channels[channel].users.join("<br />"));
Index.displayUsers(channel);
}
});

@@ -512,10 +579,6 @@ $(document).ready(() => {
$inputbox.on("keydown", () => Index.setSize($inputbox));
$inputbox.on("keyup", () => Index.setSize($inputbox));

$("#inputbox").emojioneArea({
shortcuts: false
});

// # ## ## # #
// # # # # # #
// ##### ## ### ### ### ### ## # ### ### ## ### ## # ## ## # #
@@ -106,7 +106,6 @@ class Twitch extends Chat {

twitch.tmi.on("connected", (address, port) => {
twitch.emit("connected", address, port);
//twitch.api.getEmoticonImages((err, emotes) => console.log(err, emotes));
});

twitch.tmi.on("disconnected", (message) => {
@@ -120,13 +119,21 @@ class Twitch extends Chat {
// });
});

// # # # # # # # # # # # #
// # # # # # # # # # #
// ### # # ## ### ## ### ### # # ## ## ### # # # # # ## ### ### ### ### ## # # #
// # # # # # # # # # #### # # # # # # #### # ## ## ## # # # # # ## #
// # #### # # # # # ## # # # # ## # # # # # # # ## ## ## # ## ## ## #
// ## #### ### ## ## # # ## ## # # ### ## ## # # # # # ## ### ### # # # ## #
// ###
twitch.tmi.on("message", (channel, userstate, text, self) => {
var span = $("<span></span>");

if (userstate.emotes) {
let emotes = {},
lastEnd = 0;

Object.keys(userstate.emotes).forEach((id) => {
Object.keys(userstate.emotes).forEach((id) => {
var ranges = userstate.emotes[id];
ranges.forEach((range) => {
var matches = rangeRegex.exec(range);
@@ -160,7 +167,7 @@ class Twitch extends Chat {
userstate.color = defaultColors[(userstate.username.charCodeAt(0) + userstate.username.charCodeAt(userstate.username.length - 1)) % defaultColors.length];
}

twitch.emit("message", channel, userstate.username, userstate.color, userstate["display-name"], span.html(), text);
twitch.emit("message", channel, userstate.username, userstate.color, userstate["display-name"], userstate.badges, span.html(), text);
});

twitch.tmi.on("join", (channel, username, self) => {
@@ -467,6 +474,7 @@ class Twitch extends Chat {
return new Promise((resolve, reject) => {
http.get("http://tmi.twitch.tv/group/user/" + channel + "/chatters", (res) => {
var body = "";

res.on("data", (chunk) => {
body += chunk;
});
@@ -478,6 +486,61 @@ class Twitch extends Chat {
});
}

// # ## # ## ### #
// # # # # # # # #
// ### ## ### # ### ### ### ### ## # ### ### ### ### ## ###
// # # # ## # # # # # # # # # # # ## # # # # # # # # # # ## ##
// ## ## # # # # # # ## # # # # ## # # # # ## # # ## ## ##
// # ## ## ## # # # # # # # # ## ### ### # # ### # ## ###
// ### ###
/**
* Gets the user badges that can be used in a channel.
* @param {string} channelID The channel ID to get user badges for.
* @return {Promise} A promise that resolves when the badges are sent.
*/
getChannelBadges(channelID) {
return new Promise((resolve, reject) => {
const fxs = [
new Promise((resolve, reject) => {
http.get("http://badges.twitch.tv/v1/badges/global/display", (res) => {
var body = "";

res.on("data", (chunk) => {
body += chunk;
});
res.on("end", () => {
JSON.tryParse(body).then(resolve).catch(reject);
});
// TODO: Handle errors on res
});
}),
new Promise((resolve, reject) => {
http.get(`http://badges.twitch.tv/v1/badges/channels/${channelID}/display?language=en`, (res) => { // TODO: Languages!
var body = "";

res.on("data", (chunk) => {
body += chunk;
});
res.on("end", () => {
JSON.tryParse(body).then(resolve).catch(reject);
});
// TODO: Handle errors on res
});
}),
];

Promise.all(fxs).then((badgeArray) => {
const [{badge_sets: globalBadges}, {badge_sets: channelBadges}] = badgeArray;

Object.keys(channelBadges).forEach((key) => {
({[key]: globalBadges[key]} = channelBadges);
});

resolve(globalBadges);
}).catch(reject);
});
}

// # ## # #
// # # # # #
// ### ## ### # ### ### ### # # ###

0 comments on commit 8f54786

Please sign in to comment.