diff --git a/pytchat/__init__.py b/pytchat/__init__.py index 61d1189..38551d5 100644 --- a/pytchat/__init__.py +++ b/pytchat/__init__.py @@ -2,7 +2,7 @@ pytchat is a lightweight python library to browse youtube livechat without Selenium or BeautifulSoup. """ __copyright__ = 'Copyright (C) 2019 taizan-hokuto' -__version__ = '0.1.7' +__version__ = '0.1.8' __license__ = 'MIT' __author__ = 'taizan-hokuto' __author_email__ = '55448286+taizan-hokuto@users.noreply.github.com' diff --git a/pytchat/cli/__init__.py b/pytchat/cli/__init__.py index 94601a3..211da9f 100644 --- a/pytchat/cli/__init__.py +++ b/pytchat/cli/__init__.py @@ -62,18 +62,30 @@ def main(): print(f" output path: {path.resolve()}") duration = info.get_duration() - pbar = ProgressBar(duration) - ex = Extractor(video_id, - processor=HTMLArchiver(Arguments().output + video_id + '.html'), + pbar = ProgressBar(total=(duration * 1000) / 0.99, status="Extracting") + ex = Extractor(video_id, callback=pbar._disp, div=10) signal.signal(signal.SIGINT, (lambda a, b: cancel(ex, pbar))) - ex.extract() + data = ex.extract() + if data == []: + return False + pbar.reset("#", "=", total=len(data), status="Rendering ") + processor = HTMLArchiver(Arguments().output + video_id + '.html', callback=pbar._disp) + processor.process( + [{'video_id': None, + 'timeout': 1, + 'chatdata': (action["replayChatItemAction"]["actions"][0] for action in data)}] + ) + processor.finalize() + pbar.reset('#', '#', status='Completed ') pbar.close() + print() if pbar.is_cancelled(): print("\nThe extraction process has been discontinued.\n") - return - print("\nThe extraction process has been completed.\n") + return False + return True + except InvalidVideoIdException: print("Invalid Video ID or URL:", video_id) except TypeError as e: diff --git a/pytchat/cli/progressbar.py b/pytchat/cli/progressbar.py index d49b825..b61d6bc 100644 --- a/pytchat/cli/progressbar.py +++ b/pytchat/cli/progressbar.py @@ -6,33 +6,46 @@ https://gist.github.com/vladignatyev/06860ec2040cb497f0f3 ''' import sys +ROT = ['\u25F4', '\u25F5', '\u25F6', '\u25F7'] + class ProgressBar: - def __init__(self, duration): - self._duration = duration - self._count = 0 + def __init__(self, total, status): self._bar_len = 60 self._cancelled = False + self.reset(total=total, status=status) + self._blinker = 0 + + def reset(self, symbol_done="=", symbol_space=" ", total=100, status=''): + self._symbol_done = symbol_done + self._symbol_space = symbol_space + self._total = total + self._status = status + self._count = 0 def _disp(self, _, fetched): - self._progress(fetched / 1000, self._duration) + self._progress(fetched, self._total) - def _progress(self, fillin, total, status=''): + def _progress(self, fillin, total): if total == 0 or self._cancelled: return self._count += fillin filled_len = int(round(self._bar_len * self._count / float(total))) percents = round(100.0 * self._count / float(total), 1) + if percents > 100: + percents = 100.0 if filled_len > self._bar_len: filled_len = self._bar_len - percents = 100 - bar = '=' * filled_len + ' ' * (self._bar_len - filled_len) - sys.stdout.write(' [%s] %s%s ...%s\r' % (bar, percents, '%', status)) + + bar = self._symbol_done * filled_len + \ + self._symbol_space * (self._bar_len - filled_len) + sys.stdout.write(' [%s] %s%s ...%s %s \r' % (bar, percents, '%', self._status, ROT[self._blinker % 4])) sys.stdout.flush() + self._blinker += 1 def close(self): if not self._cancelled: - self._progress(self._duration, self._duration) + self._progress(self._total, self._total) def cancel(self): self._cancelled = True diff --git a/pytchat/processors/html_archiver.py b/pytchat/processors/html_archiver.py index 5e2e423..3a1b913 100644 --- a/pytchat/processors/html_archiver.py +++ b/pytchat/processors/html_archiver.py @@ -43,20 +43,21 @@ class HTMLArchiver(ChatProcessor): ''' HTMLArchiver saves chat data as HTML table format. ''' - def __init__(self, save_path): + def __init__(self, save_path, callback): super().__init__() self.save_path = self._checkpath(save_path) self.processor = DefaultProcessor() self.emoji_table = {} # tuble for custom emojis. key: emoji_id, value: base64 encoded image binary. self.header = [HEADER_HTML] self.body = ['
\n', '