# Election vote-counting, result-posting chatbot

In preparation for the end of Code Review's 2015 election, I've built a simple bot to get the election votes, run OpenSTV on them, and post the result to a chatroom. I'm using this Python implementation of STV and ManishEarth's ChatExchange.

import getpass
import logging
import os
import time
import urllib
import sys
from subprocess import call

import ChatExchange.chatexchange
from ChatExchange.chatexchange.events import MessageEdited

logging.captureWarnings(True)

class bcolors:
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'

logging.basicConfig(level=logging.CRITICAL)

if 'ChatExchangeU' in os.environ:
email = os.environ['ChatExchangeU']
else:
email = raw_input("Email: ")
if 'ChatExchangeP' in os.environ:
else:

raw_input(bcolors.BOLD + bcolors.OKGREEN + "Connection good." + bcolors.ENDC + bcolors.BOLD + " [Enter] to proceed getting results for " + sys.argv[1] + " election #" + sys.argv[2] + "..." + bcolors.ENDC)

result_indented = ""

for string in result.splitlines():
result_indented = result_indented + "    " + string + "\n"

print result_indented

winners_line = ">" + result_indented.splitlines()[-1]

okay_to_post = raw_input("Okay to post? ")
if okay_to_post.lower() == "y":
sandbox = client.get_room(sys.argv[3])
sandbox.send_message(winners_line)
sandbox.send_message(result_indented, False)

time.sleep(40)


I run it from the command line like so:

python StackElectChat.py <site> <election number> <chatroom id>


For example, running this:

python StackElectChat.py serverfault.com 2 17251


Would take the results from Server Fault's second election and post it to Chatroom #17251.

Some concerns:

• I don't like how I'm doing colors for it (taken from this Stack Overflow answer), is there a built in way?
• okay_to_post.lower() seems like a hack - is there a built in way to check for an affirmative answer to a request?
• I don't like how I iterate over every line to add code formatting (four spaces) to the chat message

To address your first concern, the way you're doing colors is fine... If you're not running Windows. If you try to use raw ANSI codes like this on windows, you're going to run into some issues. Personally, I'd recommend using the Colorama. It's pretty easy to use. For example, if I wanted to print yellow text with a red background, I'd do this:

from colorama import init, Fore, Back

init()

print(Fore.YELLOW + Back.RED + "Text!")


Secondly, using str.lower on input, isn't really all that hacky, and it's done quite a lot when obtaining user input. In short, it's okay.

Finally, I'm noticing that you're using string concatenation to display variables in a string. The proper way to do this would be to use str.format. Here's how that'd be done:

# Normal str.format without positional or
# named parameters.
print "{} {}".format("Hello", "world")

# str.format with positional parameters (*args)
print "{1} {0}".format("world", "Hello")

# str.format with named parameters (**kwargs)
print "{word1} {word2}".format(word1="Hello", word2="world")


result_indented = ""

for string in result.splitlines():
result_indented = result_indented + "    " + string + "\n"

print result_indented

winners_line = ">" + result_indented.splitlines()[-1]


The Pythonic way to build result_indented would be using a list comprehension. But a bigger problem here is the wasteful splitlines twice. A better way to write this:

result_indented = ['    {}\n'.format(x) for x in result.splitlines()]
print(''.join(result_indented))

winners_line = '> ' + result_indented[-1]