mirror of
https://git.teknik.io/Teknikode/Teknik.git
synced 2023-08-02 14:16:22 +02:00
- Hooked up handling of irc messages/commands for the UI of the client.
- Added guest access and requesting of login when logging in as user.
This commit is contained in:
parent
b7e00579b5
commit
987d4bc679
46
Teknik/Areas/IRC/Content/IRC.css
Normal file
46
Teknik/Areas/IRC/Content/IRC.css
Normal file
@ -0,0 +1,46 @@
|
||||
.clientOutput {
|
||||
height: 500px;
|
||||
text-align:left;
|
||||
margin:0 auto;
|
||||
margin-bottom:25px;
|
||||
padding:10px;
|
||||
background:#fff;
|
||||
border:1px solid #ACD8F0;
|
||||
overflow:auto;
|
||||
}
|
||||
|
||||
.locationList {
|
||||
list-style: none;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.locationList .locationTab {
|
||||
border-top: 1px solid #666;
|
||||
border-left: 1px solid #666;
|
||||
border-bottom: 1px solid #666;
|
||||
border-right: 8px solid #666;
|
||||
background-color: #ddd;
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.locationList .locationTab:hover {
|
||||
border-right: 8px solid #333;
|
||||
}
|
||||
|
||||
.locationList .locationTab.selected {
|
||||
border-left: none;
|
||||
background-color: #fff;
|
||||
border-right: 8px solid #006699;
|
||||
}
|
||||
|
||||
.locationList .locationTab a,
|
||||
.locationList .locationTab a:visited {
|
||||
text-decoration: none;
|
||||
color: #666;
|
||||
display: block;
|
||||
padding: 15px 5px;
|
||||
}
|
||||
|
||||
.locationList .locationTab a:hover {
|
||||
color: #000;
|
||||
}
|
@ -12,8 +12,10 @@ namespace Teknik.Areas.IRC.Controllers
|
||||
[TeknikAuthorize]
|
||||
public class IRCController : DefaultController
|
||||
{
|
||||
public ActionResult Index()
|
||||
[AllowAnonymous]
|
||||
public ActionResult Client()
|
||||
{
|
||||
ViewBag.Title = "Web Client - " + Config.Title + " IRC";
|
||||
ClientViewModel model = new ClientViewModel();
|
||||
return View(model);
|
||||
}
|
||||
|
@ -20,16 +20,22 @@ namespace Teknik.Areas.IRC
|
||||
{
|
||||
Config config = Config.Load();
|
||||
context.MapSubdomainRoute(
|
||||
"IRC.Index", // Route name
|
||||
"IRC.Client", // Route name
|
||||
new List<string>() { "irc" },
|
||||
new List<string>() { config.Host },
|
||||
"", // URL with parameters
|
||||
new { controller = "IRC", action = "Index" }, // Parameter defaults
|
||||
new { controller = "IRC", action = "Client" }, // Parameter defaults
|
||||
new[] { typeof(Controllers.IRCController).Namespace }
|
||||
);
|
||||
|
||||
// Register Script Bundle
|
||||
BundleTable.Bundles.Add(new CdnStyleBundle("~/Content/irc", config.CdnHost).Include(
|
||||
"~/Areas/IRC/Content/IRC.css"));
|
||||
|
||||
// Register Script Bundle
|
||||
BundleTable.Bundles.Add(new CdnScriptBundle("~/bundles/irc", config.CdnHost).Include(
|
||||
"~/Scripts/bootbox/bootbox.min.js",
|
||||
"~/Scripts/jquery.blockUI.js",
|
||||
"~/Areas/IRC/Scripts/IRC.js"));
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,247 @@
|
||||
$(document).ready(function () {
|
||||
var clientViews = [];
|
||||
var serverView = '--Server--';
|
||||
var currentLocation = serverView;
|
||||
var currentNick;
|
||||
var connected = false;
|
||||
|
||||
$(document).ready(function () {
|
||||
// UI interaction
|
||||
$('#message').bind("enterKey", function (e) {
|
||||
sendMessage($('#message').val());
|
||||
$('#message').val('');
|
||||
});
|
||||
|
||||
$('#sendMessage').click(function () {
|
||||
sendMessage($('#message').val());
|
||||
$('#message').val('');
|
||||
});
|
||||
|
||||
$('#guestSignIn').click(function () {
|
||||
var result = irc.server.connect();
|
||||
if (result && result != '') {
|
||||
$('#clientLogin').hide();
|
||||
$('#client').show();
|
||||
}
|
||||
else {
|
||||
$("#verifyStatus").css('display', 'inline', 'important');
|
||||
$("#verifyStatus").html('<div class="alert alert-success alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>Unable to Connect</div>');
|
||||
}
|
||||
});
|
||||
|
||||
$('#verifyModal').on('shown.bs.modal', function (e) {
|
||||
$('#verifyPassword').focus();
|
||||
});
|
||||
|
||||
$('#verifyModal').on('hide.bs.modal', function (e) {
|
||||
$("#verifyStatus").css('display', 'none', 'important');
|
||||
$("#verifyStatus").html('');
|
||||
$('#verifyPassword').val('');
|
||||
});
|
||||
|
||||
$('#verifySubmit').click(function () {
|
||||
var username = $('#verifyUsername').val();
|
||||
var password = $('#verifyPassword').val();
|
||||
var result = irc.server.connect(username, password);
|
||||
if (result) {
|
||||
$('#clientLogin').hide();
|
||||
$('#client').show();
|
||||
$('#verifyModal').modal('hide');
|
||||
}
|
||||
else {
|
||||
$("#verifyStatus").css('display', 'inline', 'important');
|
||||
$("#verifyStatus").html('<div class="alert alert-success alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>Unable to Login</div>');
|
||||
}
|
||||
});
|
||||
|
||||
function sendMessage(message) {
|
||||
irc.server.sendMessage(currentLocation, message);
|
||||
}
|
||||
|
||||
$('#message').keyup(function (e) {
|
||||
if (e.keyCode == 13) {
|
||||
$(this).trigger("enterKey");
|
||||
}
|
||||
});
|
||||
|
||||
/* ----------------------------------------
|
||||
Websocket for the irc client
|
||||
-----------------------------------------*/
|
||||
var irc = $.connection.ircClient;
|
||||
|
||||
irc.client.rawMessageReceived = function (message) {
|
||||
var txt = $('#clientOutput');
|
||||
txt.val(txt.val() + '\n' + message);
|
||||
irc.client.privateMessageCommand = function (message) {
|
||||
var msg = formatMessage(message.TimeStamp, currentNick + ': ' + message.Message);
|
||||
addOutput(message.Recipient, msg);
|
||||
};
|
||||
|
||||
irc.client.privateNoticeCommand = function (message) {
|
||||
var msg = formatMessage(message.TimeStamp, currentNick + ' -NOTICE-: ' + message.Message);
|
||||
addOutput(currentLocation, msg);
|
||||
};
|
||||
|
||||
irc.client.channelMessage = function (message) {
|
||||
var msg = formatMessage(message.TimeStamp, message.Sender.Nickname + ': ' + message.Message);
|
||||
addOutput(message.Channel, msg);
|
||||
};
|
||||
|
||||
irc.client.channelNotice = function (message) {
|
||||
var msg = formatMessage(message.TimeStamp, message.Sender.Nickname + ': ' + message.Message);
|
||||
addOutput(currentLocation, msg);
|
||||
};
|
||||
|
||||
irc.client.channelModeChange = function (message, modes) {
|
||||
var msg = formatMessage(message.TimeStamp, ' * ' + message.Nick.Nickname + ' sets mode ' + modes);
|
||||
addOutput(message.Channel, msg);
|
||||
};
|
||||
|
||||
irc.client.privateMessage = function (message) {
|
||||
var location = message.Sender.Nickname;
|
||||
if (location.toLowerCase() == 'nickserv' || location.toLowerCase() == 'chanserv') {
|
||||
location = serverView;
|
||||
}
|
||||
var msg = formatMessage(message.TimeStamp, message.Sender.Nickname + ': ' + message.Message);
|
||||
addOutput(location, msg);
|
||||
};
|
||||
|
||||
irc.client.privateNotice = function (message) {
|
||||
var msg = formatMessage(message.TimeStamp, message.Sender.Nickname + ' -NOTICE-: ' + message.Message);
|
||||
addOutput(currentLocation, msg);
|
||||
};
|
||||
|
||||
irc.client.ctcpMessage = function (message) {
|
||||
var msg = formatMessage(message.TimeStamp, '[CTCP] [' + message.Command + '] ' + message.Sender.Nickname + ': ' + message.Arguments);
|
||||
addOutput(message.Location, msg);
|
||||
};
|
||||
|
||||
irc.client.joinChannel = function (message) {
|
||||
var msg = formatMessage(message.TimeStamp, message.Nick.Nickname + ' has joined ' + message.Channel);
|
||||
addOutput(message.Channel, msg);
|
||||
};
|
||||
|
||||
irc.client.inviteChannel = function (message) {
|
||||
var msg = formatMessage(message.TimeStamp, ' * ' + message.Requester.Nickname + ' invited ' + message.Recipient.Nickname);
|
||||
addOutput(message.Channel, msg);
|
||||
};
|
||||
|
||||
irc.client.partChannel = function (message) {
|
||||
var msg = formatMessage(message.TimeStamp, message.Nick.Nickname + ' has left ' + message.Channel);
|
||||
addOutput(message.Channel, msg);
|
||||
};
|
||||
|
||||
irc.client.quit = function (message) {
|
||||
var quitMsg = message.Nick.Nickname;
|
||||
if (message.Message != '') {
|
||||
quitMsg = message.Message;
|
||||
}
|
||||
var msg = formatMessage(message.TimeStamp, message.Nick.Nickname + ' has quit: (' + quitMsg + ')');
|
||||
addOutput(message.Channel, msg);
|
||||
};
|
||||
|
||||
irc.client.kick = function (message) {
|
||||
var msg = formatMessage(message.TimeStamp, ' * ' + message.Nick.Nickname + ' has kicked ' + message.KickedNick.Nickname + ' (' + message.Reason + ')');
|
||||
addOutput(message.Channel, msg);
|
||||
};
|
||||
|
||||
irc.client.topicChange = function (message) {
|
||||
var msg = formatMessage(message.TimeStamp, ' * ' + message.Nick.Nickname + ' has changed the topic to: ' + message.Topic);
|
||||
addOutput(message.Channel, msg);
|
||||
};
|
||||
|
||||
irc.client.userModeChange = function (message, modes) {
|
||||
var msg = formatMessage(message.TimeStamp, ' * ' + message.Nick.Nickname + ' sets mode ' + modes);
|
||||
addOutput(currentLocation, msg);
|
||||
};
|
||||
|
||||
irc.client.nickChange = function (message) {
|
||||
var msg = formatMessage(message.TimeStamp, ' * ' + message.OldNick.Nickname + ' is now known as ' + message.NewNick.Nickname);
|
||||
addOutput(currentLocation, msg);
|
||||
};
|
||||
|
||||
irc.client.serverReply = function (message) {
|
||||
var msg = formatMessage(message.TimeStamp, '*: ' + message.Message);
|
||||
addOutput(serverView, msg);
|
||||
};
|
||||
|
||||
irc.client.serverError = function (message) {
|
||||
var msg = formatMessage(message.TimeStamp, '*: ' + message.Message);
|
||||
addOutput(serverView, msg);
|
||||
};
|
||||
|
||||
irc.client.connected = function () {
|
||||
connected = true;
|
||||
};
|
||||
|
||||
irc.client.disconnected = function () {
|
||||
connected = false;
|
||||
};
|
||||
|
||||
irc.client.exception = function (exception) {
|
||||
$("#top_msg").css('display', 'inline', 'important');
|
||||
$("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>' + exception + '</div>');
|
||||
};
|
||||
|
||||
irc.client.nickChanged = function (nickname) {
|
||||
currentNick = nickname;
|
||||
$('#clientTitle').html('<p>Logged in as: <strong>' + nickname + '</strong></p>');
|
||||
};
|
||||
|
||||
$.connection.hub.start();
|
||||
});
|
||||
|
||||
$('#sendMessage').click(function () {
|
||||
irc.server.sendRawMessage($('#message').val());
|
||||
$('#message').val('');
|
||||
function formatMessage(timeStamp, message) {
|
||||
var timeStamp = new Date(timeStamp);
|
||||
var msg = '[' + timeStamp.getHours() + ':' + timeStamp.getMinutes() + ':' + timeStamp.getSeconds() + '] : ' + message;
|
||||
return msg;
|
||||
}
|
||||
|
||||
function addOutput(location, message) {
|
||||
// If the current view is the same location as the output, append it to the view
|
||||
if (currentLocation == location) {
|
||||
var txt = $('#clientOutput');
|
||||
if (txt.text() == '') {
|
||||
txt.text(message);
|
||||
}
|
||||
else {
|
||||
txt.text(txt.text() + '\n' + message);
|
||||
}
|
||||
txt.scrollTop(txt[0].scrollHeight);
|
||||
}
|
||||
|
||||
// Add it to the in memory buffer for this location
|
||||
var clientView = getClientView(location);
|
||||
if (clientView) {
|
||||
clientView.output.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
function changeClientView(location) {
|
||||
var clientView = getClientView(location);
|
||||
if (clientView) {
|
||||
currentLocation = location;
|
||||
$('#clientOutput').text(clientView.output.join('\n'));
|
||||
$('#clientOutput').scrollTop($('#clientOutput')[0].scrollHeight);
|
||||
}
|
||||
}
|
||||
|
||||
function getClientView(location) {
|
||||
// Get the item from the master list
|
||||
var foundView = clientViews.find(function (item) {
|
||||
return item.location === location;
|
||||
});
|
||||
});
|
||||
if (!foundView) {
|
||||
foundView = createClientView(location);
|
||||
}
|
||||
return foundView;
|
||||
}
|
||||
|
||||
function createClientView(location) {
|
||||
// Create new view item
|
||||
var item = { location: location, output: [] };
|
||||
clientViews.push(item);
|
||||
// Add the new location to the UI
|
||||
var itemDiv = $('<li class="locationTab" id="' + location + '"><a href="#">' + location + '</a></li>');
|
||||
itemDiv.find('a').click(function () {
|
||||
changeClientView(location);
|
||||
});
|
||||
$('#locationList').append(itemDiv);
|
||||
return item;
|
||||
}
|
90
Teknik/Areas/IRC/Views/IRC/Client.cshtml
Normal file
90
Teknik/Areas/IRC/Views/IRC/Client.cshtml
Normal file
@ -0,0 +1,90 @@
|
||||
@model Teknik.Areas.IRC.ViewModels.ClientViewModel
|
||||
|
||||
@using Teknik.Utilities
|
||||
|
||||
@Styles.Render("~/Content/irc")
|
||||
|
||||
@if (Model.Config.UserConfig.LoginEnabled)
|
||||
{
|
||||
<div class="modal fade" id="verifyModal" tabindex="-1" role="dialog" aria-labelledby="verifyModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-sm">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header modal-header-default">
|
||||
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title" id="verifyModalLabel">Teknik Login</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 text-center">
|
||||
<div id="verifyStatus">
|
||||
@if (Model.Error)
|
||||
{
|
||||
<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button></div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form id="verifyForm" action="#" method="post" accept-charset="UTF-8">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" id="verifyUsername" value="@((User.Identity.IsAuthenticated) ? User.Info.Username : string.Empty)" placeholder="Username" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="password" class="form-control" id="verifyPassword" value="" placeholder="Password" />
|
||||
</div>
|
||||
<div class="form-group text-center">
|
||||
<button class="btn btn-primary" id="verifySubmit" type="button">Sign In</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 text-center">
|
||||
<h2>Teknik IRC Web Client</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container" id="clientLogin">
|
||||
<div class="row">
|
||||
<div class="col-sm-5"><h2 class="text-center">Sign In as Guest</h2></div>
|
||||
<div class="col-sm-2"><h2 class="text-center">or</h2></div>
|
||||
<div class="col-sm-5"><h2 class="text-center">Sign In with Teknik Account</h2></div>
|
||||
</div>
|
||||
<br />
|
||||
<div class="row">
|
||||
<div class="col-sm-5"><button type="button" class="btn btn-primary center-block" id="guestSignIn">Enter as Guest</button></div>
|
||||
<div class="col-sm-5 col-sm-offset-2"><button type="button" class="btn btn-primary center-block" id="accountSignIn" data-toggle="modal" data-target="#verifyModal">Sign In</button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container" id="client" style="display:none">
|
||||
<div class="row">
|
||||
<div class="col-sm-12" id="clientTitle"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-10">
|
||||
<pre class="clientOutput" id="clientOutput"></pre>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<ul class="locationList" id="locationList">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="message" id="message">
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<button type="button" class="btn btn-primary" id="sendMessage">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@Scripts.Render("~/bundles/signalr")
|
||||
@Scripts.Render("~/signalr/hubs")
|
||||
@Scripts.Render("~/bundles/irc")
|
@ -1,35 +0,0 @@
|
||||
@model Teknik.Areas.IRC.ViewModels.ClientViewModel
|
||||
|
||||
@using Teknik.Utilities
|
||||
|
||||
@Scripts.Render("~/bundles/signalr")
|
||||
@Scripts.Render("~/signalr/hubs")
|
||||
@Scripts.Render("~/bundles/irc")
|
||||
|
||||
<div class="container">
|
||||
@if (User.Identity.IsAuthenticated)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-sm-10">
|
||||
<textarea class="form-control" name="clientOutput" id="clientOutput" rows="20"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div class="row">
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="message" id="message">
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<button type="button" class="btn btn-primary" id="sendMessage">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-sm-10 col-sm-offset-1">
|
||||
<p>You need to be authenticated to view this page.</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
@ -13,8 +13,6 @@ namespace Teknik.Areas.Users.ViewModels
|
||||
{
|
||||
public class LoginViewModel : ViewModelBase
|
||||
{
|
||||
private TeknikEntities db = new TeknikEntities();
|
||||
|
||||
[Required]
|
||||
[Display(Name = "Username")]
|
||||
public string Username { get; set; }
|
||||
|
@ -7,66 +7,156 @@ using System.Web;
|
||||
using Teknik.Attributes;
|
||||
using Teknik.SignalR;
|
||||
using System.Threading.Tasks;
|
||||
using System.Timers;
|
||||
using Teknik.Areas.Users.Utility;
|
||||
using Teknik.Areas.Users.Models;
|
||||
using Teknik.Models;
|
||||
using Teknik.Configuration;
|
||||
using Teknik.Utilities;
|
||||
|
||||
namespace Teknik.Hubs
|
||||
{
|
||||
[HubName("ircClient")]
|
||||
[TeknikAuthorize]
|
||||
public class IRCClientHub : Hub
|
||||
{
|
||||
private static Dictionary<string, IRCClient> _Clients = new Dictionary<string, IRCClient>();
|
||||
private static Dictionary<string, string> _Connections = new Dictionary<string, string>();
|
||||
private static Dictionary<string, Tuple<IRCClient, Timer>> _Clients = new Dictionary<string, Tuple<IRCClient, Timer>>();
|
||||
private const int _DisconnectTimeout = 30; // Timeout to disconnect from IRC server after client disconnects from hub (Seconds)
|
||||
|
||||
public IRCClientHub()
|
||||
{
|
||||
}
|
||||
|
||||
public override Task OnConnected()
|
||||
public override Task OnDisconnected(bool stopCalled)
|
||||
{
|
||||
// Get the username for this connection
|
||||
string username = string.Empty;
|
||||
if (Context != null)
|
||||
{
|
||||
if (!_Clients.ContainsKey(Context.ConnectionId))
|
||||
if (_Connections.ContainsKey(Context.ConnectionId))
|
||||
{
|
||||
if (Context.User.Identity.IsAuthenticated)
|
||||
{
|
||||
// Add the new connection to the main list
|
||||
_Clients.Add(Context.ConnectionId, new IRCClient(Clients.Caller));
|
||||
// Get the username
|
||||
username = _Connections[Context.ConnectionId];
|
||||
|
||||
// Auto Connect to the server at startup
|
||||
Connect();
|
||||
}
|
||||
// Remove this connection from the list
|
||||
_Connections.Remove(Context.ConnectionId);
|
||||
}
|
||||
}
|
||||
|
||||
return base.OnConnected();
|
||||
}
|
||||
|
||||
public override Task OnDisconnected(bool stopCalled)
|
||||
{
|
||||
if (_Clients.ContainsKey(Context.ConnectionId))
|
||||
// Start disconnect timer for this user
|
||||
if (_Clients.ContainsKey(username))
|
||||
{
|
||||
// Disconnect from the IRC session
|
||||
_Clients[Context.ConnectionId].Disconnect();
|
||||
|
||||
// Remove the irc client
|
||||
_Clients.Remove(Context.ConnectionId);
|
||||
// Start disconnect timer
|
||||
_Clients[username].Item2.Start();
|
||||
}
|
||||
|
||||
return base.OnDisconnected(stopCalled);
|
||||
}
|
||||
|
||||
public void Connect()
|
||||
public string Connect()
|
||||
{
|
||||
// Create guest username
|
||||
string username = "Guest_" + StringHelper.RandomString(6, "0123456789");
|
||||
Connect(username, string.Empty);
|
||||
|
||||
return username;
|
||||
}
|
||||
|
||||
public bool Connect(string username, string password)
|
||||
{
|
||||
if (_Clients.ContainsKey(Context.ConnectionId))
|
||||
bool success = true;
|
||||
// If the password is supplied, verify the password
|
||||
if (!string.IsNullOrEmpty(password))
|
||||
{
|
||||
_Clients[Context.ConnectionId].Connect(Context.User.Identity.Name);
|
||||
TeknikEntities db = new TeknikEntities();
|
||||
User user = UserHelper.GetUser(db, username);
|
||||
if (user != null)
|
||||
{
|
||||
Config config = Config.Load();
|
||||
success = UserHelper.UserPasswordCorrect(db, config, user, password);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
// Update this connection with the username associated we want to associate with it
|
||||
if (Context != null)
|
||||
{
|
||||
if (!_Connections.ContainsKey(Context.ConnectionId))
|
||||
{
|
||||
_Connections.Add(Context.ConnectionId, string.Empty);
|
||||
}
|
||||
_Connections[Context.ConnectionId] = username;
|
||||
}
|
||||
|
||||
// Add the client for this user if it doesn't exist
|
||||
if (!_Clients.ContainsKey(username))
|
||||
{
|
||||
// Client doesn't exist, so create it
|
||||
Timer disconnectTimer = new Timer(_DisconnectTimeout * 1000);
|
||||
disconnectTimer.Elapsed += (sender, e) => DisconnectTimer_Elapsed(sender, e, username);
|
||||
|
||||
// Add the new connection to the main list
|
||||
_Clients.Add(username, new Tuple<IRCClient, Timer>(new IRCClient(Clients.Caller), disconnectTimer));
|
||||
}
|
||||
|
||||
// Stop the disconnect timer because we have reconnected
|
||||
_Clients[username].Item2.Stop();
|
||||
|
||||
// Reassociate this connection with the user
|
||||
_Clients[username].Item1.CallerContext = Clients.Caller;
|
||||
|
||||
// Connect
|
||||
_Clients[username].Item1.Connect(username, password);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public void SendMessage(string location, string message)
|
||||
{
|
||||
string username = GetConnectionUser();
|
||||
if (_Clients.ContainsKey(username))
|
||||
{
|
||||
_Clients[username].Item1.SendMessage(location, message);
|
||||
}
|
||||
}
|
||||
|
||||
public void SendRawMessage(string message)
|
||||
{
|
||||
if (_Clients.ContainsKey(Context.ConnectionId))
|
||||
string username = GetConnectionUser();
|
||||
if (_Clients.ContainsKey(username))
|
||||
{
|
||||
_Clients[Context.ConnectionId].SendRawMessage(message);
|
||||
_Clients[username].Item1.SendRawMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
private void DisconnectTimer_Elapsed(object sender, ElapsedEventArgs e, string username)
|
||||
{
|
||||
if (_Clients.ContainsKey(username))
|
||||
{
|
||||
// Disconnect from the IRC session
|
||||
_Clients[username].Item1.Disconnect();
|
||||
|
||||
// Remove the irc client
|
||||
_Clients.Remove(username);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetConnectionUser()
|
||||
{
|
||||
if (Context != null)
|
||||
{
|
||||
if (_Connections.ContainsKey(Context.ConnectionId))
|
||||
{
|
||||
return _Connections[Context.ConnectionId];
|
||||
}
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
@ -11,6 +11,8 @@ using Microsoft.AspNet.SignalR.Hubs;
|
||||
using Teknik.Configuration;
|
||||
using System.Net;
|
||||
using Teknik.Utilities;
|
||||
using System.Timers;
|
||||
using IRCSharp.Commanding;
|
||||
|
||||
namespace Teknik.SignalR
|
||||
{
|
||||
@ -18,6 +20,19 @@ namespace Teknik.SignalR
|
||||
{
|
||||
private IRC _IRC;
|
||||
private dynamic _CallerContext;
|
||||
public dynamic CallerContext
|
||||
{
|
||||
get
|
||||
{
|
||||
return _CallerContext;
|
||||
}
|
||||
set
|
||||
{
|
||||
_CallerContext = value;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _Guest;
|
||||
|
||||
// State Variables
|
||||
private bool _Connected = false;
|
||||
@ -35,6 +50,8 @@ namespace Teknik.SignalR
|
||||
|
||||
public IRCClient(dynamic callerContext)
|
||||
{
|
||||
_Guest = false;
|
||||
|
||||
Config config = Config.Load();
|
||||
_CallerContext = callerContext;
|
||||
|
||||
@ -44,11 +61,45 @@ namespace Teknik.SignalR
|
||||
_IRC.DisconnectEvent += HandleDisconnectEvent;
|
||||
_IRC.ExceptionThrown += HandleIrcExceptionThrown;
|
||||
|
||||
// Handle Message Events
|
||||
_IRC.Message.RawMessageEvent += Message_RawMessageEvent;
|
||||
|
||||
_IRC.Message.ChannelMessageReceivedEvent += Message_ChannelMessageReceivedEvent;
|
||||
_IRC.Message.ChannelNoticeReceivedEvent += Message_ChannelNoticeReceivedEvent;
|
||||
_IRC.Message.ChannelModeChangeEvent += Message_ChannelModeChangeEvent;
|
||||
|
||||
_IRC.Message.PrivateMessageReceivedEvent += Message_PrivateMessageReceivedEvent;
|
||||
_IRC.Message.PrivateNoticeReceivedEvent += Message_PrivateNoticeReceivedEvent;
|
||||
|
||||
_IRC.Message.CTCPMessageReceivedEvent += Message_CTCPMessageReceivedEvent;
|
||||
_IRC.Message.CTCPNoticeReceivedEvent += Message_CTCPNoticeReceivedEvent;
|
||||
|
||||
_IRC.Message.JoinChannelEvent += Message_JoinChannelEvent;
|
||||
_IRC.Message.InviteChannelEvent += Message_InviteChannelEvent;
|
||||
_IRC.Message.PartChannelEvent += Message_PartChannelEvent;
|
||||
_IRC.Message.QuitEvent += Message_QuitEvent;
|
||||
_IRC.Message.KickEvent += Message_KickEvent;
|
||||
_IRC.Message.TopicChangeEvent += Message_TopicChangeEvent;
|
||||
_IRC.Message.UserModeChangeEvent += Message_UserModeChangeEvent;
|
||||
_IRC.Message.NickChangeEvent += Message_NickChangeEvent;
|
||||
|
||||
_IRC.Message.ServerReplyEvent += Message_ServerReplyEvent;
|
||||
|
||||
// Handle Command Events
|
||||
_IRC.Command.PrivateMessageCommandEvent += Command_PrivateMessageCommandEvent;
|
||||
_IRC.Command.PrivateNoticeCommandEvent += Command_PrivateNoticeCommandEvent;
|
||||
}
|
||||
|
||||
public void Connect(string username)
|
||||
public void Connect()
|
||||
{
|
||||
// Create guest username
|
||||
string username = "Guest_" + StringHelper.RandomString(6, "0123456789");
|
||||
Connect(username, string.Empty);
|
||||
}
|
||||
|
||||
public void Connect(string username, string password)
|
||||
{
|
||||
_Guest = string.IsNullOrEmpty(password);
|
||||
if (!_Connected)
|
||||
{
|
||||
Config config = Config.Load();
|
||||
@ -64,13 +115,24 @@ namespace Teknik.SignalR
|
||||
|
||||
if (_Connected)
|
||||
{
|
||||
_IRC.Login("Teknik-WebClient", new Nick()
|
||||
// Login
|
||||
_IRC.Login(config.Title + "-WebClient", new Nick()
|
||||
{
|
||||
Nickname = username,
|
||||
Host = Dns.GetHostName(),
|
||||
Host = config.Host,
|
||||
Realname = username,
|
||||
Username = username
|
||||
});
|
||||
|
||||
// Fire off event about current nick
|
||||
_CallerContext.nickChanged(username);
|
||||
|
||||
// Try to identify if not guest
|
||||
if (!_Guest)
|
||||
{
|
||||
// Identify to NickServ if need be
|
||||
_IRC.Command.SendPrivateMessage("NickServ", string.Format("IDENTIFY {0}", password));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -91,11 +153,197 @@ namespace Teknik.SignalR
|
||||
}
|
||||
}
|
||||
|
||||
private void Message_RawMessageEvent(object sender, string message)
|
||||
/// <summary>
|
||||
/// Process the message and for commands, execute their command, otherwise send a private message
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public void SendMessage(string location, string message)
|
||||
{
|
||||
_CallerContext.rawMessageReceived(message);
|
||||
if (_Connected)
|
||||
{
|
||||
// Process Command
|
||||
if (message.StartsWith("/"))
|
||||
{
|
||||
string[] msgSplit = message.Split(' ');
|
||||
string cmd = msgSplit[0].Remove(0, 1);
|
||||
string actualMessage = string.Empty;
|
||||
if (msgSplit.Length > 1)
|
||||
{
|
||||
actualMessage = string.Join(" ", msgSplit.Skip(1).Take(msgSplit.Length - 1));
|
||||
}
|
||||
ProcessCommand(cmd, actualMessage, location);
|
||||
}
|
||||
else
|
||||
{
|
||||
_IRC.Command.SendPrivateMessage(location, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessCommand(string command, string message, string location)
|
||||
{
|
||||
switch (command.ToLower())
|
||||
{
|
||||
case "join":
|
||||
_IRC.Command.SendJoin(message);
|
||||
break;
|
||||
case "part":
|
||||
_IRC.Command.SendPart(message);
|
||||
break;
|
||||
case "invite":
|
||||
_IRC.Command.SendInvite(location, message);
|
||||
break;
|
||||
case "list":
|
||||
_IRC.Command.SendList(message);
|
||||
break;
|
||||
case "action":
|
||||
_IRC.Command.SendCTCPMessage(location, "ACTION", message);
|
||||
break;
|
||||
case "query":
|
||||
string rec = string.Empty;
|
||||
string msg = string.Empty;
|
||||
string[] querySplit = message.Split(' ');
|
||||
if (querySplit.Length > 0)
|
||||
{
|
||||
rec = querySplit[0];
|
||||
}
|
||||
if (querySplit.Length > 1)
|
||||
{
|
||||
msg = string.Join(" ", querySplit.Skip(1).Take(querySplit.Length - 1));
|
||||
}
|
||||
_IRC.Command.SendPrivateMessage(rec, msg);
|
||||
break;
|
||||
case "notice":
|
||||
string notRec = string.Empty;
|
||||
string notMsg = string.Empty;
|
||||
string[] notSplit = message.Split(' ');
|
||||
if (notSplit.Length > 0)
|
||||
{
|
||||
notRec = notSplit[0];
|
||||
}
|
||||
if (notSplit.Length > 1)
|
||||
{
|
||||
notMsg = string.Join(" ", notSplit.Skip(1).Take(notSplit.Length - 1));
|
||||
}
|
||||
_IRC.Command.SendNotice(notRec, notMsg);
|
||||
break;
|
||||
case "raw":
|
||||
_IRC.Command.SendRaw(message);
|
||||
break;
|
||||
default:
|
||||
_CallerContext.exception($"Command not recognized: {command}");
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Message Events
|
||||
private void Message_RawMessageEvent(object sender, string message)
|
||||
{
|
||||
_CallerContext.rawMessage(message);
|
||||
}
|
||||
|
||||
private void Message_ServerReplyEvent(object sender, IReply e)
|
||||
{
|
||||
if (e.GetType() == typeof(ServerReplyMessage))
|
||||
{
|
||||
ServerReplyMessage reply = (ServerReplyMessage)e;
|
||||
_CallerContext.serverReply(reply);
|
||||
}
|
||||
else if (e.GetType() == typeof(ServerErrorMessage))
|
||||
{
|
||||
ServerErrorMessage error = (ServerErrorMessage)e;
|
||||
_CallerContext.serverError(error);
|
||||
}
|
||||
}
|
||||
|
||||
private void Message_NickChangeEvent(object sender, NickChangeInfo e)
|
||||
{
|
||||
_CallerContext.nickChange(e);
|
||||
}
|
||||
|
||||
private void Message_UserModeChangeEvent(object sender, UserModeChangeInfo e)
|
||||
{
|
||||
_CallerContext.userModeChange(e, e.Modes.ModesToString());
|
||||
}
|
||||
|
||||
private void Message_TopicChangeEvent(object sender, TopicChangeInfo e)
|
||||
{
|
||||
_CallerContext.topicChange(e);
|
||||
}
|
||||
|
||||
private void Message_KickEvent(object sender, KickInfo e)
|
||||
{
|
||||
_CallerContext.kick(e);
|
||||
}
|
||||
|
||||
private void Message_QuitEvent(object sender, QuitInfo e)
|
||||
{
|
||||
_CallerContext.quit(e);
|
||||
}
|
||||
|
||||
private void Message_PartChannelEvent(object sender, PartChannelInfo e)
|
||||
{
|
||||
_CallerContext.partChannel(e);
|
||||
}
|
||||
|
||||
private void Message_InviteChannelEvent(object sender, InviteChannelInfo e)
|
||||
{
|
||||
_CallerContext.inviteChannel(e);
|
||||
}
|
||||
|
||||
private void Message_JoinChannelEvent(object sender, JoinChannelInfo e)
|
||||
{
|
||||
_CallerContext.joinChannel(e);
|
||||
}
|
||||
|
||||
private void Message_CTCPNoticeReceivedEvent(object sender, CTCPMessage e)
|
||||
{
|
||||
_CallerContext.ctcpMessage(e);
|
||||
}
|
||||
|
||||
private void Message_CTCPMessageReceivedEvent(object sender, CTCPMessage e)
|
||||
{
|
||||
_CallerContext.ctcpMessage(e);
|
||||
}
|
||||
|
||||
private void Message_PrivateNoticeReceivedEvent(object sender, PrivateNotice e)
|
||||
{
|
||||
_CallerContext.privateNotice(e);
|
||||
}
|
||||
|
||||
private void Message_PrivateMessageReceivedEvent(object sender, PrivateMessage e)
|
||||
{
|
||||
_CallerContext.privateMessage(e);
|
||||
}
|
||||
|
||||
private void Message_ChannelModeChangeEvent(object sender, ChannelModeChangeInfo e)
|
||||
{
|
||||
_CallerContext.channelModeChange(e, e.Modes.ModesToString());
|
||||
}
|
||||
|
||||
private void Message_ChannelNoticeReceivedEvent(object sender, ChannelNotice e)
|
||||
{
|
||||
_CallerContext.channelNotice(e);
|
||||
}
|
||||
|
||||
private void Message_ChannelMessageReceivedEvent(object sender, ChannelMessage e)
|
||||
{
|
||||
_CallerContext.channelMessage(e);
|
||||
}
|
||||
|
||||
// Handle Command Events
|
||||
private void Command_PrivateNoticeCommandEvent(object sender, PrivateNoticeCommand e)
|
||||
{
|
||||
_CallerContext.privateNoticeCommand(e);
|
||||
}
|
||||
|
||||
private void Command_PrivateMessageCommandEvent(object sender, PrivateMessageCommand e)
|
||||
{
|
||||
_CallerContext.privateMessageCommand(e);
|
||||
}
|
||||
|
||||
// Handle IRC events
|
||||
private void HandleIrcExceptionThrown(Exception obj)
|
||||
{
|
||||
_CallerContext.exception(obj.GetFullMessage(true));
|
||||
|
@ -393,6 +393,7 @@
|
||||
<Content Include="Areas\Help\Content\Help.css" />
|
||||
<Content Include="Areas\Home\Content\Home.css" />
|
||||
<Content Include="Areas\Home\Scripts\Home.js" />
|
||||
<Content Include="Areas\IRC\Content\IRC.css" />
|
||||
<Content Include="Areas\IRC\Scripts\IRC.js" />
|
||||
<Content Include="Areas\Paste\Content\Paste.css" />
|
||||
<Content Include="Areas\Paste\Scripts\Paste.js" />
|
||||
@ -656,7 +657,7 @@
|
||||
<Content Include="Areas\Admin\Views\Admin\UploadSearch.cshtml" />
|
||||
<Content Include="Areas\Admin\Views\Admin\UploadResult.cshtml" />
|
||||
<Content Include="Areas\IRC\Views\web.config" />
|
||||
<Content Include="Areas\IRC\Views\IRC\Index.cshtml" />
|
||||
<Content Include="Areas\IRC\Views\IRC\Client.cshtml" />
|
||||
<Content Include="Areas\IRC\Views\_ViewStart.cshtml" />
|
||||
<None Include="Properties\PublishProfiles\Teknik Dev.pubxml" />
|
||||
<None Include="Properties\PublishProfiles\Teknik Production.pubxml" />
|
||||
|
Loading…
Reference in New Issue
Block a user