public object ExecuteAction(ChatAction action)
        {
            if (disposed) { return null; }

            var key = queuedActions.Keys.Count == 0 ? 0 : queuedActions.Keys.Max() + 1;
            var mre = new ManualResetEvent(false);
            object data = null;

            ActionCompleted += (k, d) =>
            {
                if (k == key)
                {
                    data = d;
                    // Action completed, notify the waiting thread.
                    mre.Set();
                }
            };

            // Add the action to the queue for processing.
            queuedActions[key] = action;

            // Wait for the action to be completed.
            mre.WaitOne();

            // The action's been processed; remove it from the queue.
            ChatAction temp;
            queuedActions.TryRemove(key, out temp);

            return data;
        }
Example #2
0
        public bool SetUserRoomAccess(UserRoomAccess access, int userID)
        {
            if (hasLeft)
            {
                throw new InvalidOperationException("Cannot change user's access level when you have left the room.");
            }
            if (!Me.IsMod || !Me.IsRoomOwner)
            {
                throw new InvalidOperationException("Unable to change user's access level. You have insufficient privileges (must be a room owner or moderator).");
            }

            var action = new ChatAction(ActionType.KickMute, new Func<object>(() =>
            {
                while (true)
                {
                    var data = "fkey=" + fkey + "&aclUserId=" + userID + "&userAccess=";

                    switch (access)
                    {
                        case UserRoomAccess.Normal:
                        {
                            data += "remove";
                            break;
                        }

                        case UserRoomAccess.ExplicitReadOnly:
                        {
                            data += "read-only";
                            break;
                        }

                        case UserRoomAccess.ExplicitReadWrite:
                        {
                            data += "read-write";
                            break;
                        }

                        case UserRoomAccess.Owner:
                        {
                            data += "owner";
                            break;
                        }
                    }

                    var resContent = RequestManager.Post(cookieKey, chatRoot + "/rooms/setuseraccess/" + ID, data);

                    if (string.IsNullOrEmpty(resContent)) { return false; }
                    if (HandleThrottling(resContent)) { continue; }

                    return true;
                }
            }));

            return (bool?)actEx.ExecuteAction(action) ?? false;
        }
Example #3
0
        public bool KickMute(int userID)
        {
            if (hasLeft)
            {
                throw new InvalidOperationException("Cannot kick-mute user when you have left the room.");
            }
            if (!Me.IsMod || !Me.IsRoomOwner)
            {
                throw new InvalidOperationException("Unable to kick-mute user. You have insufficient privileges (must be a room owner or moderator).");
            }

            var action = new ChatAction(ActionType.KickMute, new Func<object>(() =>
            {
                while (true)
                {
                    var data = "userID=" + userID + "&fkey=" + fkey;
                    var resContent = RequestManager.Post(cookieKey, chatRoot + "/rooms/kickmute/" + ID, data);

                    if (string.IsNullOrEmpty(resContent)) { return false; }
                    if (HandleThrottling(resContent)) { continue; }

                    return resContent != null && resContent.Contains("has been kicked");
                }
            }));

            return (bool?)actEx.ExecuteAction(action) ?? false;
        }
Example #4
0
        public bool TogglePin(int messageID)
        {
            if (hasLeft)
            {
                throw new InvalidOperationException("Cannot toggle message pin when you have left the room.");
            }
            if (!Me.IsMod || !Me.IsRoomOwner)
            {
                throw new InvalidOperationException("Unable to toggle a message pin. You have insufficient privileges (must be a room owner or moderator).");
            }

            var action = new ChatAction(ActionType.ToggleMessagePin, new Func<object>(() =>
            {
                while (true)
                {
                    var data = "fkey=" + fkey;
                    var resContent = RequestManager.Post(cookieKey, chatRoot + "/messages/" + messageID + "/owner-star", data);

                    if (string.IsNullOrEmpty(resContent)) { return false; }
                    if (HandleThrottling(resContent)) { continue; }

                    return resContent == "\"ok\"";
                }
            }));

            return (bool?)actEx.ExecuteAction(action) ?? false;
        }
Example #5
0
        public bool ToggleStar(int messageID)
        {
            if (hasLeft)
            {
                throw new InvalidOperationException("Cannot toggle message star when you have left the room.");
            }

            var action = new ChatAction(ActionType.ToggleMessageStar, new Func<object>(() =>
            {
                while (!disposed)
                {
                    var resContent = RequestManager.Post(cookieKey, chatRoot + "/messages/" + messageID + "/star", "fkey=" + fkey);

                    if (string.IsNullOrEmpty(resContent) || hasLeft) { return false; }
                    if (HandleThrottling(resContent)) { continue; }

                    return resContent != "\"ok\"";
                }

                return false;
            }));

            return (bool?)actEx.ExecuteAction(action) ?? false;
        }
Example #6
0
        public bool EditMessage(int messageID, object newMessage)
        {
            if (newMessage == null || string.IsNullOrEmpty(newMessage.ToString()))
            {
                throw new ArgumentException("'newMessage' cannot be null or return an empty/null string upon calling .ToString().", "newMessage");
            }
            if (hasLeft)
            {
                throw new InvalidOperationException("Cannot edit message when you have left the room.");
            }

            var action = new ChatAction(ActionType.EditMessage, new Func<object>(() =>
            {
                while (!disposed)
                {
                    var data = "text=" + Uri.EscapeDataString(newMessage.ToString()).Replace("%5Cn", "%0A") + "&fkey=" + fkey;
                    var resContent = RequestManager.Post(cookieKey, chatRoot + "/messages/" + messageID, data);

                    if (string.IsNullOrEmpty(resContent) || hasLeft) { return false; }
                    if (HandleThrottling(resContent)) { continue; }

                    return resContent == "\"ok\"";
                }

                return false;
            }));

            return (bool?)actEx.ExecuteAction(action) ?? false;
        }
Example #7
0
        /// <summary>
        /// Posts a new message in the room without: parsing the
        /// action's response or throwing any exceptions.
        /// (Benchmarks show an approximate performance increase of
        /// 3.5x-9.5x depending on network capabilities.)
        /// </summary>
        /// <param name="message">The message to post.</param>
        /// <returns>True if the message was successfully posted, otherwise false.</returns>
        public bool PostMessageFast(object message)
        {
            if (message == null || string.IsNullOrEmpty(message.ToString()) || hasLeft ||
                CheckDupeMsg(message.ToString()) != null || Me.Reputation < 20)
            {
                return false;
            }

            var action = new ChatAction(ActionType.PostMessage, new Func<object>(() =>
            {
                while (!disposed)
                {
                    var data = "text=" + Uri.EscapeDataString(message.ToString()).Replace("%5Cn", "%0A") + "&fkey=" + fkey;
                    var resContent = RequestManager.Post(cookieKey, chatRoot + "/chats/" + ID + "/messages/new", data);

                    if (string.IsNullOrEmpty(resContent) || hasLeft) { return false; }
                    if (HandleThrottling(resContent)) { continue; }

                    return JsonObject.Parse(resContent).ContainsKey("id");
                }

                return false;
            }));

            return (bool)actEx.ExecuteAction(action);
        }
Example #8
0
        /// <summary>
        /// Posts a new message in the room.
        /// </summary>
        /// <param name="message">The message to post.</param>
        /// <returns>A Message object representing the newly posted message (if successful), otherwise returns null.</returns>
        public Message PostMessage(object message)
        {
            if (message == null || string.IsNullOrEmpty(message.ToString()))
            {
                throw new ArgumentException("'message' cannot be null or return an empty/null string upon calling .ToString().", "message");
            }
            if (hasLeft)
            {
                throw new InvalidOperationException("Cannot post message when you have left the room.");
            }
            if (Me.Reputation < 20)
            {
                throw new Exception("You must have at least 20 reputation to post a message.");
            }
            var ex = CheckDupeMsg(message.ToString());
            if (ex != null)
            {
                throw ex;
            }

            var action = new ChatAction(ActionType.PostMessage, new Func<object>(() =>
            {
                while (!disposed)
                {
                    var data = "text=" + Uri.EscapeDataString(message.ToString()).Replace("%5Cn", "%0A") + "&fkey=" + fkey;
                    var resContent = RequestManager.Post(cookieKey, chatRoot + "/chats/" + ID + "/messages/new", data);

                    if (string.IsNullOrEmpty(resContent) || hasLeft) { return null; }
                    if (HandleThrottling(resContent)) { continue; }

                    var json = JsonObject.Parse(resContent);
                    var messageID = -1;
                    if (json.ContainsKey("id"))
                    {
                        messageID = json.Get<int>("id");
                    }
                    else
                    {
                        return null;
                    }

                    return this[messageID];
                }

                return null;
            }));

            return (Message)actEx.ExecuteAction(action);
        }