Turns out libpurple has separate signals for direct IMs and chat messages - handling both now