Skip to content

Commit

Permalink
Can now log a list of specific channels
Browse files Browse the repository at this point in the history
  • Loading branch information
bernardopires committed Jul 29, 2015
1 parent 2295c2f commit 7b79456
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 30 deletions.
21 changes: 14 additions & 7 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ twitch-chat-logger

A simple python app for logging twitch's chat to a PostgreSQL database. It
logs an arbitrary ammount of channels (default is a 100) ordered by the
numbers of viewers. Twitch seems to not like a single bot joining a large
amount of channels, so each bot is limitted to 20 channels. This app
automatically scales the number of bots according to how many channels are
to be logged (e.g. logging a 100 channels will result in 5 bots being created).
The list of most popular channels is updated every 60 seconds and the bots
join and leave channels as needed.
numbers of viewers or an specific list of channels. Twitch seems to not like
a single bot joining a large amount of channels, so each bot is limitted to
20 channels. This app automatically scales the number of bots according to how
many channels are to be logged (e.g. logging a 100 channels will result in
5 bots being created). The list of most popular channels is updated every 60
seconds and the bots join and leave channels as needed.

Logging 100 channels for 24 hours seems to amount to ~4 million chat lines
(~400 MB).
Expand Down Expand Up @@ -76,7 +76,8 @@ you may have to execute ``apt-get install libpq-dev python-dev``.
python main.py

The command above will start 5 bots logging the 100 most popular twitch
channels. To log a different amount use the parameter ``n`` and to save the
channels. To log a different amount use the parameter ``n``, to log a
specific list of channels use the parameter ``c`` and to save the
output to a file use the parameter ``f``. For example, use the command below
to log the 50 most popular channels with the output being saved to a file
named ``log.txt``
Expand All @@ -85,6 +86,12 @@ named ``log.txt``

python main.py -n 50 -f log.txt

To log a specific list of channels, separate the channels name by whitespace.

::

python main.py -c channel1 channel2 channel3

.. _Twitch Chat OAuth Password Generator: http://twitchapps.com/tmi/
.. _docker: https://www.docker.com/
.. _fig: http://www.fig.sh/
Expand Down
10 changes: 6 additions & 4 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@

def main():
parser = argparse.ArgumentParser()
parser.add_argument("-n", "--streams-to-log", dest="streams_to_log", type=int,
help="the number of streams to log", default=100)
parser.add_argument("-n", "--streams-to-log", dest="channels_amount", type=int,
help="the number of streams to log", default=100)
parser.add_argument("-f", "--log-filename", dest="log_filename",
help="the filename to log to", default=None)
help="the filename to log to", default=None)
parser.add_argument("-c", "--channels", dest="channels", type=str, nargs='+',
help="the specific channel names to log", default=[])
args = parser.parse_args()

manager = TwitchManager(streams_to_log=args.streams_to_log, log_filename=args.log_filename)
manager = TwitchManager(channels_amount=args.channels_amount, channels=args.channels, log_filename=args.log_filename)
try:
manager.run_log_loop()
except KeyboardInterrupt:
Expand Down
49 changes: 30 additions & 19 deletions manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ class TwitchManager:
SECONDS_BETWEEN_UPDATE_STREAMS = 60
SECONDS_BETWEEN_CREATE_BOTS = 15

def __init__(self, streams_to_log, log_filename=None):
def __init__(self, channels_amount, channels, log_filename=None):
self.bots = []
self.streams_to_log = streams_to_log
self.channels_amount = channels_amount
self.log_filename = log_filename
self.channels = channels
self.db_logger = DatabaseLogger(settings.DATABASE['HOST'],
settings.DATABASE['NAME'],
settings.DATABASE['USER'],
Expand All @@ -42,29 +43,23 @@ def _create_bot(self, name, channels):
bot.start()
return bot

def _create_bots(self, streams_to_log):
def _create_bots(self, channels):
"""
Creates bots to log all the desired streams.
Creates bots to log the given list of channels.
Twitch limits how many channels can be joined per connection, so we
create just enough bots to log all the desired streams. There's also
a timeout between opening connections otherwise Twitch disconnects
all bots.
"""
streams = get_top_streams(streams_to_log)
channels = get_channel_names(streams)

channels_joined = 0
while channels_joined < streams_to_log:
# create a new bot
while channels_joined < len(channels):
self.bots.append(
self._create_bot('Bot %i' % len(self.bots),
channels[channels_joined:channels_joined + self.CHANNELS_PER_BOT]))
channels_joined += self.CHANNELS_PER_BOT
time.sleep(self.SECONDS_BETWEEN_CREATE_BOTS)

self._log_streams(streams)

def _update_bot_channels(self, bot, new_channels):
channels_to_remove = list(set(bot.channels) - set(new_channels))
channels_to_add = list(set(new_channels) - set(bot.channels))
Expand All @@ -79,27 +74,43 @@ def _log_streams(self, streams):
for stream in streams:
self.db_logger.log_stream_stats(stream)

def run_log_loop(self):
"""
Creates the logger bots and update which stream they log every 60
seconds.
"""
self._create_bots(self.streams_to_log)
def _run_popular_streams_loop(self):
streams = get_top_streams(self.channels_amount)
channels = get_channel_names(streams)
self._create_bots(channels)
self._log_streams(streams)

while True:
time.sleep(self.SECONDS_BETWEEN_UPDATE_STREAMS)
streams = get_top_streams(self.streams_to_log)
streams = get_top_streams(self.channels_amount)
channels = get_channel_names(streams)

i, channels_joined = 0, 0
while channels_joined < self.streams_to_log:
while channels_joined < self.channels_amount:
self._update_bot_channels(self.bots[i],
channels[channels_joined:channels_joined + self.CHANNELS_PER_BOT])
i += 1
channels_joined += self.CHANNELS_PER_BOT

self._log_streams(streams)

def _run_static_streams_loop(self):
self._create_bots(self.channels)
while True:
time.sleep(self.SECONDS_BETWEEN_UPDATE_STREAMS)
#streams = get_top_streams(self.channels_amount)
#self._log_streams(streams)

def run_log_loop(self):
"""
Creates the logger bots and update which stream they log every 60
seconds.
"""
if self.channels:
self._run_static_streams_loop()
else:
self._run_popular_streams_loop()

def stop_bot(self):
for bot in self.bots:
bot.join()

0 comments on commit 7b79456

Please sign in to comment.