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(''', "'")
+ 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()