Permalink
Browse files

Updates from week 4, including the fix to the Bootstrap tabs issue (C…

…SS conflicts).
  • Loading branch information...
roncli committed Apr 11, 2017
1 parent aee0f65 commit 402bf17b861525414cbf7162c0b8e17cd0d64674
@@ -17,7 +17,7 @@ body {
flex-grow: 1;
}

#display > .tab-pane {
#display > .tab-pane.active {
display: flex;
flex-direction: row;
width: 100%;
@@ -1,28 +1,18 @@
<html>
<head>
<script src="js/index.js"></script>
<script src="../node_modules/jquery/dist/jquery.min.js"></script>
<script>$ = jQuery = require("jquery")</script>
<script src="../node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="js/index.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"></script>
<link href="css/index.css" rel="stylesheet"></link>
</head>
<body>
<div id="menu">Menu</div>
<div id="channels">
<ul class="nav nav-tabs">
<li><a data-toggle="tab" href="#channel-roncli">#roncli</a>
</ul>
</div>
<div id="display" class="tab-content">
<div role="tabpanel" class="tab-pane active" id="channel-roncli">
<div class="chat" id="chat">
<div id="topic"></div>
<div id="text"></div>
</div>
<div class="users" id="users"></div>
</div>
<ul id="channels" class="nav nav-tabs">
</ul>
<div id="display" class="tab-content panel">
</div>
<div id="input">
<input type="text" id="inputbox" />
@@ -0,0 +1,14 @@
JSON.tryParse = (str) => {
var initialStr = str;
return new Promise((resolve, reject) => {
if (!str || str.length === 0) {
reject();
};
str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').replace(/(?:^|:|,)(?:\s*\[)+/g, '');
if ((/^[\],:{}\s]*$/).test(str)) {
resolve(JSON.parse(initialStr));
} else {
reject();
}
});
};
@@ -1,42 +1,118 @@
var Twitch = require("./modules/chat/twitch"), // TODO: Load modules
var electron = require("electron"),
path = require("path"),
Twitch = require("./modules/chat/twitch"), // TODO: Load modules
File = require("./modules/datastore/file"),
settings = require("./js/settings"),
client = new Twitch(settings),
channels = {};

client.on("connected", (address, port) => {
document.getElementById("text").innerHTML += `Connected on address ${address} port ${port}<br />`;
});
userSettings = new File(path.join(electron.remote.app.getPath("userData"), "userSettings.js"));
channels = {},
getTab = (username) => {
return `<li id="tab-${username}"><a data-toggle="tab" href="#channel-${username}">#${username}</a></li>`;
},
getPanel = (username) => {
return `<div role="tabpanel" class="tab-pane" id="channel-${username}">
<div class="chat" class="chat">
<div class="topic"></div>
<div class="text"></div>
</div>
<div class="users" class="users"></div>
</div>`;
};

client.on("message", (channel, username, displayname, text) => {
document.getElementById("text").innerHTML += `<b>${displayname}</b>: ${text}<br />`;
console.log("message", channel, username, text);
$(`#channel-${channel.substring(1)} .text`).append(`<b>${displayname}</b>: ${text}<br />`);
});

client.on("join", (channel, username, self) => {
console.log("join", channel, username);
if (self) {
channels[channel] = {
users: []
};
$("#channels").append(getTab(channel.substring(1)));
$("#display").append(getPanel(channel.substring(1)));
}
channels[channel].users.push(username);
document.getElementById("text").innerHTML += `<i>${(self ? "You have" : `${username} has`)} joined ${channel}<br />`;
document.getElementById("users").innerHTML = channels[channel].users.join("<br />");
$(`#channel-${channel.substring(1)} .text`).append(`<i>${(self ? "You have" : `${username} has`)} joined ${channel}<br />`);
$(`#channel-${channel.substring(1)} .users`).html(channels[channel].users.join("<br />"));
});

client.on("part", (channel, username, self) => {
channels[channel].users.splice(channels[channel].users.indexOf(username), 1);
document.getElementById("text").innerHTML += `<i>${(self ? "You have" : `${username} has`)} left ${channel}<br />`;
document.getElementById("users").innerHTML = channels[channel].users.join("<br />");
if (self) {
$(`#tab-${channel.substring(1)}`).remove();
$(`#channel-${channel.substring(1)}`).remove();
}
$(`#channel-${channel.substring(1)} .text`).append(`<i>${(self ? "You have" : `${username} has`)} left ${channel}<br />`);
$(`#channel-${channel.substring(1)} .users`).html(channels[channel].users.join("<br />"));
});

client.on("mod", (channel, username) => {
document.getElementById("text").innerHTML += `<i>${username} is now a moderator of ${channel}<br />`;
$(`#channel-${channel.substring(1)} .text`).append(`<i>${username} is now a moderator of ${channel}<br />`);
});

client.on("unmod", (channel, username) => {
document.getElementById("text").innerHTML += `<i>${username} is no longer a moderator of ${channel}<br />`;
$(`#channel-${channel.substring(1)} .text`).append(`<i>${username} is no longer a moderator of ${channel}<br />`);
});

client.authorize().then(() => {
client.connect().then(() => {
channels["#roncli"] = {
users: []
};
client.on("credentials", (username, accessToken) => {
if (!userSettings.data.twitch) {
userSettings.data.twitch = {};
}

userSettings.queue(() => {
userSettings.data.twitch.username = username;
userSettings.data.twitch.accessToken = accessToken;
}).then(() => {
userSettings.save();
});
});

userSettings.load().then(() => {
new Promise((resolve, reject) => {
if (userSettings.data && userSettings.data.twitch) {
client.authorize(userSettings.data.twitch.username, userSettings.data.twitch.accessToken).then(resolve);
} else {
client.authorize().then(resolve);
}
}).then(() => {
client.connect().then(() => {
client.join("#roncli");
});
});
});

$(document).ready(() => {
var $inputbox = $("#inputbox");

$inputbox.on("keypress", (ev) => {
if (ev.keyCode === 13 && client.connected) {
let input = $inputbox.val(),
matches;

matches = /^\/join #?([a-z0-9_]+)$/i.exec(input);

if (matches) {
let channel = matches[1].toLowerCase();
client.join(`#${channel}`);
return;
}

matches = /^\/part$/i.exec(input);

if (matches) {
client.part($("#channels li.active").text());
return;
}

client.send($("#channels li.active").text(), $inputbox.val());
$inputbox.val("");
}
});

client.join("#roncli");
$("#channels").on("click", "a", (ev) => {
ev.preventDefault();
$(this).tab("show");
});
});
@@ -0,0 +1,10 @@
function Queue() {
this.promise = Promise.resolve();
return this;
}

Queue.prototype.push = function(fx) {
this.promise = this.promise.then(() => {}).catch(() => {}).then(fx);
};

module.exports = Queue;
@@ -1,8 +1,8 @@
var Chat = require("../../../js/base/chat"),
electron = require("electron"),
var electron = require("electron"),
Tmi = require("tmi.js"),
TwitchApi = require("twitch-api");

TwitchApi = require("twitch-api"),
Chat = require("../../../js/base/chat");

class Twitch extends Chat {
constructor (settings) {
super();
@@ -13,7 +13,7 @@ class Twitch extends Chat {
}

get connected() {
// TODO: Return whether or not we're connected to TMI.
return this.tmi.readyState() === "OPEN";
}

connect() {
@@ -34,7 +34,10 @@ class Twitch extends Chat {
}

settings = twitch.settings.tmi;
settings.identity.password = `oauth:${twitch.accessToken}`;
settings.identity = {
username: twitch.username,
password: `oauth:${twitch.accessToken}`
};

twitch.tmi = new Tmi.client(settings);

@@ -75,8 +78,14 @@ class Twitch extends Chat {
twitch.emit("unmod", channel, username);
});

/*
twitch.tmi.on("notice", (a, b, c) => {
console.log(a, b, c);
});
*/

twitch.tmi.connect().then(() => {
twitch.tmi.raw("CAP REQ :twitch.tv/membership");
twitch.tmi.raw("CAP REQ :twitch.tv/membership twitch.tv/commands twitch.tv/tags");

resolve();
}).catch((err) => {
@@ -90,42 +99,79 @@ class Twitch extends Chat {
return !!(this.accessToken);
}

authorize() {
var twitch = this,
api = this.api,
win = new electron.remote.BrowserWindow({width: 800, height: 600, parent: electron.remote.BrowserWindow.getAllWindows().find((w) => w.getTitle() === "Hyperdrive Toolkit"), modal: true, title: "Hyperdrive Toolkit - Waiting for Twitch OAuth"});

authorize(username, accessToken) {
var twitch = this;

return new Promise((resolve, reject) => {
win.loadURL(`file://${__dirname}/twitch.htm`);
win.setMenu(null);
var api = twitch.api;

win.once("ready-to-show", () => {
win.show();
});
new Promise((innerResolve, innerReject) => {
if (username && accessToken) {
api.getAuthenticatedUser(accessToken, (err, body) => {
if (err) {
innerReject();
// TODO: Handle the error more gracefully.
}

win.on("access-token", (accessToken) => {
twitch.accessToken = accessToken;
});
twitch.accessToken = accessToken;
twitch.username = body.name;
twitch.displayName = body.display_name;

twitch.emit("credentials", twitch.username, twitch.accessToken);

win.on("closed", () => {
win = null;
if (twitch.accessToken) {
resolve();
innerResolve();
});
} else {
reject();
innerReject();
}
}).then(resolve).catch(() => {
var win = new electron.remote.BrowserWindow({width: 800, height: 600, parent: electron.remote.BrowserWindow.getAllWindows().find((w) => w.getTitle() === "Hyperdrive Toolkit"), modal: true, title: "Hyperdrive Toolkit - Waiting for Twitch OAuth"});

win.loadURL(`file://${__dirname}/twitch.htm`);
win.setMenu(null);

win.once("ready-to-show", () => {
win.show();
});

win.on("access-token", (accessToken) => {
twitch.accessToken = accessToken;
api.getAuthenticatedUser(twitch.accessToken, (err, body) => {
if (err) {
// TODO: Handle the error more gracefully.
}

twitch.username = body.name;
twitch.displayName = body.display_name;

twitch.emit("credentials", twitch.username, twitch.accessToken);
});
});

win.on("closed", () => {
win = null;
if (twitch.accessToken) {
resolve();
} else {
reject();
}
});

electron.shell.openExternal(api.getAuthorizationUrl().replace("response_type=code", "response_type=token") + "&force_verify=true");
});

electron.shell.openExternal(api.getAuthorizationUrl().replace("response_type=code", "response_type=token") + "&force_verify=true");
});
}

join(channel) {
this.tmi.join(channel);
return this.tmi.join(channel);
}

part(channel) {
this.tmi.part(channel);
return this.tmi.part(channel);
}

send(channel, command) {
return this.tmi.say(channel, command);
}
}

Oops, something went wrong.

0 comments on commit 402bf17

Please sign in to comment.