- 
      
 - 
        
Save tinyapps/df2b6757a142ff93caf9c63d0ef38b11 to your computer and use it in GitHub Desktop.  
| #!/usr/bin/env python3 | |
| """ | |
| SPDX-License-Identifier: MIT https://opensource.org/licenses/MIT | |
| Copyright © 2021 [email protected] | |
| * Input file is an info.json (with comments) that yt-dlp (https://github.com/yt-dlp/yt-dlp) wrote | |
| * Change FIELDS according to your needs | |
| The output file will be in the format: | |
| [{ | |
| 'text': 'comment 1', | |
| ... | |
| 'replies': [{ | |
| 'text': 'reply 1', | |
| ... | |
| 'replies': [...], | |
| }, ...], | |
| }, ...] | |
| """ | |
| import json | |
| import argparse | |
| from datetime import datetime | |
| def get_fields(dct): | |
| for name, fn in FIELDS.items(): | |
| val = fn(dct, name) | |
| if val is not None: | |
| yield name, val | |
| def filter_func(comments): | |
| return [dict(get_fields(c)) for c in comments] | |
| FIELDS = { | |
| 'text': dict.get, | |
| 'author': dict.get, | |
| 'timestamp': lambda dct, name: dct.get(name) and datetime.strftime( | |
| datetime.utcfromtimestamp(dct.get(name)), '%Y/%m/%d'), | |
| 'replies': lambda dct, name: filter_func(dct.get(name, [])) or None | |
| } | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument( | |
| '--input-file', '-i', | |
| dest='inputfile', metavar='FILE', required=True, | |
| help='File to read info_dict from') | |
| parser.add_argument( | |
| '--output-file', '-o', | |
| dest='outputfile', metavar='FILE', required=True, | |
| help='File to write comments to') | |
| args = parser.parse_args() | |
| print('Reading file') | |
| with open(args.inputfile, encoding='utf-8') as f: | |
| info_dict = json.load(f) | |
| comment_data = {c['id']: c for c in sorted( | |
| info_dict['comments'], key=lambda c: c.get('timestamp') or 0)} | |
| count = len(info_dict['comments']) | |
| del info_dict | |
| nested_comments = [] | |
| for i, (cid, c) in enumerate(comment_data.items(), 1): | |
| print(f'Processing comment {i}/{count}', end='\r') | |
| parent = nested_comments if c['parent'] == 'root' else comment_data[c['parent']].setdefault('replies', []) | |
| parent.append(c) | |
| print('\nWriting file') | |
| with open(args.outputfile, 'w', encoding='utf-8') as f: | |
| json.dump(filter_func(nested_comments), f, indent=4, ensure_ascii=False) | |
| print('Done') | 
Thanks for testing it @m3jorri, as well as for your kind feedback in @pukkandan's original gist.
Thanks for your efforts and quick responses! If I may request a feature, would it be possible to add a dark mode toggle switch to the html output file?
My pleasure, @m3jorri. While it's not a toggle switch, adding these few lines just above the closing style tag will display the HTML in dark mode-friendly format if the user environment is set to dark mode:
            @media (prefers-color-scheme: dark) {
                body {
                    background-color: #121212;
                    color: #e0e0e0;
                }
                .comment-box {
                    border-color: #444;
                }
            }
I've updated the gist as well. Thanks again for testing and offering feedback.
That works, thanks
Hello, @tinyapps
Thank you for your work, on this script!
(and to pukkandan too!)
Please if you have time and strength could you implement this:
- Would it be possible to integrate the comment's up/down votes too?
 - To write comments in descending order based on upvotes (highest first)?
 
I wish I cold help but have no Idea.
Thanks again:
Hetsz.
To write comments in descending order based on upvotes (highest first)?
This is not necessary because it can be decided when the comments are downloaded with yt-dlp by specifying "youtube:comment_sort=top"
The up/down votes would be cool af to have.
Also idk how hard this is but if i was able to click a parent comment and only then show replies this would be the perfect script imo. This way replies would be hidden by default.
I wish i had the skills to make it happen.
Great script!
Also idk how hard this is but if i was able to click a parent comment and only then show replies this would be the perfect script imo. This way replies would be hidden by default.
I made a small change that adds collapsible replies here, in case anyone is interested:
https://gist.github.com/MrKomodoDragon/4a933e8deabb14f82f47eb44165fecfd
@MrKomodoDragon its exactly what i myself was missing. thanks for sharing man looks great!
Seems to work perfectly!