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; }
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; }
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; }
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; }
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; }
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; }
/// <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); }
/// <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); }