Add a simple timeline command - toot - Unnamed repository; edit this file 'description' to name the repository.
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
 (DIR) commit 5297430483c328579d664cd92e9726a311880c97
 (DIR) parent 61a12d31babc8c67987a38bfbe6bb487a867288e
 (HTM) Author: Ivan Habunek <ivan@habunek.com>
       Date:   Thu, 13 Apr 2017 13:14:01 +0200
       
       Add a simple timeline command
       
       Diffstat:
         setup.py                            |       3 ++-
         toot/__init__.py                    |      30 +++++++++++++++++++++++++-----
         toot/console.py                     |      66 +++++++++++++++++++++++++++++--
       
       3 files changed, 90 insertions(+), 9 deletions(-)
       ---
 (DIR) diff --git a/setup.py b/setup.py
       @@ -30,7 +30,8 @@ setup(
            packages=['toot'],
            install_requires=[
                'requests ~= 2.13',
       -        'future'
       +        'beautifulsoup4 ~= 4.5.3',
       +        'future',
            ],
            entry_points={
                'console_scripts': [
 (DIR) diff --git a/toot/__init__.py b/toot/__init__.py
       @@ -9,6 +9,26 @@ APP_NAME = 'toot'
        DEFAULT_INSTANCE = 'mastodon.social'
        
        
       +def _get(app, user, url, params=None):
       +    url = app.base_url + url
       +    headers = {"Authorization": "Bearer " + user.access_token}
       +
       +    response = requests.get(url, params, headers=headers)
       +    response.raise_for_status()
       +
       +    return response.json()
       +
       +
       +def _post(app, user, url, data=None):
       +    url = app.base_url + url
       +    headers = {"Authorization": "Bearer " + user.access_token}
       +
       +    response = requests.post(url, data, headers=headers)
       +    response.raise_for_status()
       +
       +    return response.json()
       +
       +
        def create_app(base_url):
            url = base_url + '/api/v1/apps'
        
       @@ -49,10 +69,10 @@ def login(app, username, password):
        
        
        def post_status(app, user, status):
       -    url = app.base_url + '/api/v1/statuses'
       -    headers = {"Authorization": "Bearer " + user.access_token}
       +    return _post(app, user, '/api/v1/statuses', {
       +        'status': status
       +    })
        
       -    response = requests.post(url, {'status': status}, headers=headers)
       -    response.raise_for_status()
        
       -    return response.json()
       +def timeline_home(app, user):
       +    return _get(app, user, '/api/v1/timelines/home')
 (DIR) diff --git a/toot/console.py b/toot/console.py
       @@ -1,11 +1,16 @@
        import os
        import sys
        
       +from bs4 import BeautifulSoup
        from builtins import input
       +from datetime import datetime
        from getpass import getpass
       +from itertools import chain
       +from textwrap import TextWrapper
       +from future.moves.itertools import zip_longest
        
        from .config import save_user, load_user, load_app, save_app, CONFIG_APP_FILE, CONFIG_USER_FILE
       -from . import create_app, login, post_status, DEFAULT_INSTANCE
       +from . import create_app, login, post_status, timeline_home, DEFAULT_INSTANCE
        
        
        def green(text):
       @@ -51,10 +56,62 @@ def print_usage():
            print("")
            print("Usage:")
            print("    toot post \"All your base are belong to us\"")
       +    print("    toot timeline")
            print("")
            print("https://github.com/ihabunek/toot")
        
        
       +def print_timeline(item):
       +    def wrap_text(text, width):
       +        wrapper = TextWrapper(width=width, break_long_words=False, break_on_hyphens=False)
       +        return chain(*[wrapper.wrap(l) for l in text.split("\n")])
       +
       +    def timeline_rows(item):
       +        name = item['name']
       +        time = item['time'].strftime('%Y-%m-%d %H:%M%Z')
       +
       +        left_column = [name, time]
       +        if 'reblogged' in item:
       +            left_column.append(item['reblogged'])
       +
       +        text = item['text']
       +
       +        right_column = wrap_text(text, 80)
       +
       +        return zip_longest(left_column, right_column, fillvalue="")
       +
       +    for left, right in timeline_rows(item):
       +        print("{:30} │ {}".format(left, right))
       +
       +
       +def parse_timeline(item):
       +    content = item['reblog']['content'] if item['reblog'] else item['content']
       +    reblogged = item['reblog']['account']['username'] if item['reblog'] else ""
       +
       +    name = item['account']['display_name'] + " @" + item['account']['username']
       +    soup = BeautifulSoup(content, "html.parser")
       +    text = soup.get_text().replace('&apos;', "'")
       +    time = datetime.strptime(item['created_at'], "%Y-%m-%dT%H:%M:%S.%fZ")
       +
       +    return {
       +        # "username": item['account']['username'],
       +        "name": name,
       +        "text": text,
       +        "time": time,
       +        "reblogged": reblogged,
       +    }
       +
       +
       +def cmd_timeline(app, user):
       +    items = timeline_home(app, user)
       +    parsed_items = [parse_timeline(t) for t in items]
       +
       +    print("─" * 31 + "┬" + "─" * 88)
       +    for item in parsed_items:
       +        print_timeline(item)
       +        print("─" * 31 + "┼" + "─" * 88)
       +
       +
        def cmd_post_status(app, user):
            if len(sys.argv) < 3:
                print(red("No status text given"))
       @@ -67,9 +124,10 @@ def cmd_post_status(app, user):
        
        def cmd_auth(app, user):
            if app and user:
       -        print("You are logged in")
       -        print("Mastodon instance: " + green(app.base_url))
       +        print("You are logged in to " + green(app.base_url))
                print("Username: " + green(user.username))
       +        print("App data:  " + green(CONFIG_APP_FILE))
       +        print("User data: " + green(CONFIG_USER_FILE))
            else:
                print("You are not logged in")
        
       @@ -88,5 +146,7 @@ def main():
                cmd_post_status(app, user)
            elif command == 'auth':
                cmd_auth(app, user)
       +    elif command == 'timeline':
       +        cmd_timeline(app, user)
            else:
                print_usage()