public override List<JSONObject> ProcessCommand(UserCommand command, UserInfo user, Dictionary<int, UserInfo> users)
      {
         List<JSONObject> outputs = new List<JSONObject>();
         ModuleJSONObject moduleOutput = new ModuleJSONObject();
         VoteBallot ballot;
         string error = "";
         string output = "";
         long pollNumber = 0;

         if (!userBallots.ContainsKey(user.UID))
            userBallots.Add(user.UID, new List<VoteBallot>());

         try
         {
            switch(command.Command)
            {
               case "pollcreate":
                  int maxPolls = MaxUserPolls * (user.CanStaffChat ? 5 : 1);
                  if (userBallots[user.UID].Count >= maxPolls)
                     return FastMessage("You've reached the maximum amount of allowed polls (" + maxPolls + ") and cannot post a new one", true);
                  else if (command.ArgumentParts[1].Count > MaxPollChoices)
                     return FastMessage("There are too many choices in your poll! The max is " + MaxPollChoices, true);

                  VoteBallot newBallot = new VoteBallot(command.Arguments[0], new HashSet<string>(command.ArgumentParts[1]));

                  if (newBallot.GetChoices().Count < 2)
                     return FastMessage("Your poll must have at least 2 options", true);

                  userBallots[user.UID].Add(newBallot);
                  moduleOutput.broadcast = true;
                  moduleOutput.message = "A new poll has been created by " + user.Username + ":\n\n" + userBallots[user.UID].Last();
                  outputs.Add(moduleOutput);

                  break;

               case "vote":

                  if(!long.TryParse(command.Arguments[1], out pollNumber))
                     return FastMessage("Your poll number is out of bounds!", true);

                  if(!GetBallot(pollNumber, false, out ballot))
                  {
                     return FastMessage("There is no open poll with ID " + pollNumber);
                  }
                  else
                  {
                     if(!ballot.AddVote(user.UID, command.Arguments[0], out error))
                        return FastMessage(error);
                     else
                        return FastMessage("You voted on this poll: \n\n" + ballot.GetResultString(user.UID));
                  }

               case "polls":
                  
                  output = "The top polls right now: \n";
                  output += PrintList(userBallots.SelectMany(x => x.Value).OrderByDescending(x => x.TotalVotes).Take(10));

                  return FastMessage(output);

               case "poll":
                  
                  if(!long.TryParse(command.Arguments[0], out pollNumber))
                     return FastMessage("Your poll number is out of bounds!", true);

                  if(!GetBallot(pollNumber, true, out ballot))
                  {
                     return FastMessage("There is no open poll with ID " + pollNumber);
                  }
                  else
                  {
                     output = "";
                     bool closed = archivedBallots.SelectMany(x => x.Value).Contains(ballot);

                     if(ballot.DidVote(user.UID) || closed)
                        output = ballot.GetResultString(user.UID);
                     else
                        output = ballot.ToString();

                     int ballotCreator = userBallots.Union(archivedBallots).First(x => x.Value.Contains(ballot)).Key;
                     output += "\nPoll by: " + users[ballotCreator].Username + (closed ? " (closed)" : "");

                     return FastMessage(output);
                  }

               case "pollclose":

                  if(!long.TryParse(command.Arguments[0], out pollNumber))
                     return FastMessage("Your poll number is out of bounds!", true);

                  if(!userBallots[user.UID].Any(x => x.ID == pollNumber))
                     return FastMessage("You don't have any open polls with this ID!");

                  if(!GetBallot(pollNumber, false, out ballot))
                  {
                     return FastMessage("There is no open poll with ID " + pollNumber);
                  }
                  else
                  {
                     if(!archivedBallots.ContainsKey(user.UID))
                        archivedBallots.Add(user.UID, new List<VoteBallot>());

                     archivedBallots[user.UID].Add(ballot);
                     userBallots[user.UID].Remove(ballot);

                     moduleOutput.broadcast = true;
                     moduleOutput.message = "The poll " + ballot.Title + " has just been closed by " + user.Username + ". The results:\n\n" + ballot.GetResultString();
                     outputs.Add(moduleOutput);
                  }

                  break;

               case "pollsearch":

                  List<Tuple<double, VoteBallot>> sortedBallots = new List<Tuple<double, VoteBallot>>();

                  foreach(VoteBallot searchBallot in userBallots.SelectMany(x => x.Value).Union(archivedBallots.SelectMany(x => x.Value)))
                     sortedBallots.Add(Tuple.Create(StringExtensions.StringDifference(command.Arguments[0].ToLower(), searchBallot.Title.ToLower()), searchBallot));

                  output = "These ballots have a similar title: \n";
                  output += PrintList(sortedBallots.OrderBy(x => x.Item1).Select(x => x.Item2).Take(SearchResults));

                  return FastMessage(output);

               case "pollsopen":

                  output = "Your open polls right now are: \n" + PrintList(userBallots[user.UID]);
                  return FastMessage(output);
            }
         }
         catch(Exception e)
         {
            return new List<JSONObject>() { 
               new ModuleJSONObject() { 
                  message = "Something terrible happened in the Vote module: " + e, broadcast = true 
               } };
         }

         return outputs;
      }
      public bool GetBallot(long pollNumber, bool useArchive, out VoteBallot ballot)
      {
         ballot = null;

         try
         {
            if(useArchive)
               ballot = userBallots.SelectMany(x => x.Value).Union(archivedBallots.SelectMany(x => x.Value)).First(x => x.ID == pollNumber);
            else
               ballot = userBallots.SelectMany(x => x.Value).First(x => x.ID == pollNumber);
            return true;
         }
         catch
         {
            return false;
         }
      }