Esempio n. 1
0
        // This controller only expects messages from clients; the Discord bridge posts to
        // DiscordMessageController.cs
        /// <summary>
        /// Sends a message from the web chat to Discord and notifies other clients to stop the typing indicator.
        /// </summary>
        /// <param name="message">The SendMessage object representing the current operation.</param>
        /// <returns>A Task representing the state of the request.</returns>
        public async Task SendMessage(SendMessage message)
        {
            // Discord bridge isn't ready, so just reject the message instead of attempting to send it
            if (!_discordBot.DiscordClient.Ready)
            {
                await this.Clients.Caller.SendAsync("BridgeDown");
            }

            // Sanitise the message contents
            NewMessage newMessage = new NewMessage(RemoveMassPings(message.Content));
            // Get the internal user by the connection ID mapping
            HubUser hubUser = UserHandler.UserMappings[this.Context.ConnectionId];

            BridgeMessage bridgeMessage = new BridgeMessage();

            // Parse the logged in user's name into a Discord ID.
            // Maybe add a check here if it fails? Users should only be able to create accounts with names from their Discord IDs
            // but unclear what happens if db is corrupted etc.
            ulong.TryParse(this.Context.User.Identity.Name, out ulong userId);
            bridgeMessage.UserId = userId;

            bridgeMessage.SignalRMessage = newMessage;

            // Send the message to the Discord client
            await _discordBot.DiscordClient.IngestSignalR(bridgeMessage);

            // Tell other clients to stop the typing indicator
            await this.Clients.Others.SendAsync("StopTypingForClient", hubUser);
        }
Esempio n. 2
0
        /// <summary>
        /// Sends other clients a typing indicator.
        /// </summary>
        /// <returns>A Task representing the state of the request.</returns>
        public async Task ClientTyping()
        {
            HubUser       hubUser       = UserHandler.UserMappings[this.Context.ConnectionId];
            TypingMessage typingMessage = new TypingMessage
            {
                // Timestamp is in milliseconds to make JavaScript side easier.
                Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString(),
                UserId    = hubUser.DiscordId
            };

            await this.Clients.Others.SendAsync("ClientTyping", typingMessage);
        }
Esempio n. 3
0
        /// <summary>
        /// Sends the client the list of users known to be connected.
        /// </summary>
        /// <returns>A Task representing the state of the request.</returns>
        public async Task GetConnectedUsers()
        {
            List <HubUser> hubUsers = new List <HubUser>();

            foreach (KeyValuePair <string, HubUser> keyValuePair in UserHandler.UserMappings)
            {
                // Get the HubUser object that's mapped to the user's connection ID
                HubUser user = keyValuePair.Value;

                if (user.HasDiscordInfo == null)
                {
                    try
                    {
                        // Try to get a DiscordMember object from Discord.
                        // Only attempts it on the first go (i.e. if it hasn't looked for one before)
                        // This isn't the default DiscordClient GetMemberById, look in Client.cs for more info.
                        // It throws an exception if it doesn't exist.
                        DiscordMember member = _discordBot.DiscordClient.GetMemberById(ulong.Parse(user.AspNetUsername)).Result;

                        // If the user is a member of the guild
                        user.HasDiscordInfo     = true;
                        user.DiscordId          = member.Id.ToString();
                        user.DiscordDisplayName = member.DisplayName;
                        // Replace GIF avatars with the first frame
                        user.AvatarUrl = member.AvatarUrl.Replace(".gif", ".png");
                    }
                    catch
                    {
                        // The user doesn't exist, stop the bot from searching again.
                        user.HasDiscordInfo = false;
                    }
                }

                // This might lead to duplicates, but if we've got multiple people
                // sharing the same Discord account with multiple connection IDs
                // then I guess it's fine to show dupes.
                hubUsers.Add(user);
            }

            await this.Clients.Caller.SendAsync("ConnectedIds", hubUsers);
        }
Esempio n. 4
0
        /// <summary>
        /// The method used to override the default connection handler to add user state tracking.
        /// </summary>
        /// <returns>A Task representing the state of the request.</returns>
        public override Task OnConnectedAsync()
        {
            lock (UserHandler.ConnectedIds)
            {
                UserHandler.ConnectedIds.Add(Context.ConnectionId);
            }

            HubUser user = new HubUser
            {
                AspNetUsername = Context.User.Identity.Name,
                HasDiscordInfo = null
            };

            UserHandler.UserMappings.TryAdd(Context.ConnectionId, user);

            UserLogger.WriteLog(Context.User.Identity.Name, Context.ConnectionId, UserLogger.ConnectionStatus.Connected);

            this.Clients.All.SendAsync("ViewerConnected");

            return(base.OnConnectedAsync());
        }