import sys
import os
-# Command abbreviations
-_ABBREVS = {
- "q": "quit",
- "p": "print",
- "c": "comments",
- "r": "reload",
- "n": "notifications",
- "e": "edit",
-}
-
_RC_PATHS = (
"~/.config/jan-pona-mute/login",
"~/.jan-pona-mute.d/login"
"ed"
)
+shortcuts = {
+ "q": "quit",
+ "p": "preview",
+ "c": "comments",
+ "r": "reload",
+ "n": "notifications",
+ "e": "edit",
+ "d": "delete",
+ "g": "notifications reload",
+}
+
def get_rcfile():
"""Init file finder"""
for path in _RC_PATHS:
connection = None
notifications = []
- index = None
+ home = None
+ numbers_refer_to = None
post = None
post_cache = {} # key is self.post.uid, and notification.id
intended, use the 'save' command to save these commands to an init
file.
-Once you've listed things such as notifications, enter a number to
-select the corresponding item.
+Once you've listed things such as notifications or the home stream,
+enter a number to select the corresponding item.
""")
def do_account(self, account):
def do_info(self, line):
"""Get some info about things. By default, it is info about yourself."""
- print("Info about yourself:")
+ print(self.header("Info"))
print("Username: %s" % self.username)
print("Password: %s" % ("None" if self.password == None else "set"))
print("Pod: %s" % self.pod)
print("Pager: %s" % self.pager)
print("Editor: %s" % self.editor)
+ print("Cache: %s posts" % len(self.post_cache))
def do_password(self, password):
"""Set the password."""
elif self.password == None:
print("Use the 'password' command.")
else:
+ print("Setting up a connection...")
self.connection = diaspy.connection.Connection(
pod = "https://%s" % self.pod, username = self.username, password = self.password)
try:
+ print("Logging in...")
self.connection.login()
- self.onecmd("notifications")
except diaspy.errors.LoginError:
print("Login failed.")
"""List notifications. Use 'notifications reload' to reload them."""
if line == "" and self.notifications:
print("Redisplaying the notifications in the cache.")
- print("Use the 'reload' argument to reload them.")
+ print("Use 'notifications reload' to reload them.")
elif line == "reload" or not self.notifications:
if self.connection == None:
print("Use the 'login' command, first.")
return
if self.notifications:
for n, notification in enumerate(self.notifications):
- print(self.header("%2d. %s %s") % (n+1, notification.when(), notification))
+ if notification.unread:
+ print(self.header("%2d. %s %s") % (n+1, notification.when(), notification))
+ else:
+ print("%2d. %s %s" % (n+1, notification.when(), notification))
print("Enter a number to select the notification.")
+ self.numbers_refer_to = 'notifications'
else:
print("There are no notifications. 😢")
# Expand abbreviated commands
first_word = line.split()[0].strip()
- if first_word in _ABBREVS:
- full_cmd = _ABBREVS[first_word]
+ if first_word in shortcuts:
+ full_cmd = shortcuts[first_word]
expanded = line.replace(first_word, full_cmd, 1)
return self.onecmd(expanded)
def do_show(self, line):
"""Show the post given by the index number.
-The index number must refer to the current list of notifications."""
- if not self.notifications:
- print("No notifications were loaded.")
- return
- if line == "":
- print("The 'show' command takes a notification number.")
- return
- try:
- n = int(line.strip())
- notification = self.notifications[n-1]
- self.index = n
- except ValueError:
- print("The 'show' command takes a notification number but '%s' is not a number" % line)
+The index number must refer to the current list of notifications
+or the home stream. If no index number is given, show the current
+post again."""
+ if not self.notifications and not self.home:
+ print("Use the 'login' command to load notifications.")
return
- except IndexError:
- print("Index too high!")
+ if line == "" and self.post == None:
+ print("Please specify a number.")
return
-
- self.show(notification)
- self.load(notification.about())
+ if line != "":
+ try:
+ n = int(line.strip())
+ if self.numbers_refer_to == 'notifications':
+ notification = self.notifications[n-1]
+ self.show(notification)
+ self.load(notification.about())
+ elif self.numbers_refer_to == 'home':
+ posts = sorted(self.home, key=lambda x: x.data()["created_at"])
+ self.post = posts[n-1]
+ else:
+ print("Internal error: not sure what numbers '%s' refer to." % self.numbers_refer_to)
+ return
+ except ValueError:
+ print("The 'show' command takes a notification number but '%s' is not a number" % line)
+ return
+ except IndexError:
+ print("Index too high!")
+ return
print()
self.show(self.post)
notes = self.get_notes()
if notes:
try:
- with open(self.get_note_path(notes[n-1]), mode = 'r', encoding = 'utf-8') as fp:
- line = fp.read()
+ line = self.read_note(notes[n-1])
print("Using note #%d: %s" % (n, notes[n-1]))
except IndexError:
print("Use the 'list notes' command to list valid numbers.")
self.undo.append("delete comment %s from %s" % (comment.id, self.post.id))
print("Comment posted.")
+ def do_post(self, line):
+ """Write a post on the current stream.
+If you just use a number as your post, it will refer to a note.
+Use the 'edit' command to edit notes."""
+ if self.home == None:
+ self.home = diaspy.streams.Stream(self.connection)
+ try:
+ # if the post is just a number, use a note to post
+ n = int(line.strip())
+ notes = self.get_notes()
+ if notes:
+ try:
+ line = self.read_note(notes[n-1])
+ print("Using note #%d: %s" % (n, notes[n-1]))
+ except IndexError:
+ print("Use the 'list notes' command to list valid numbers.")
+ return
+ else:
+ print("There are no notes to use.")
+ return
+ except ValueError:
+ # in which case we'll simply post the line
+ pass
+ self.post = self.home.post(text = line)
+ self.post_cache[self.post.id] = self.post
+ self.undo.append("delete post %s" % self.post.id)
+ print("Posted. Use the 'show' command to show it.")
+
def do_delete(self, line):
"""Delete a comment."""
words = line.strip().split()
if notes:
for n, note in enumerate(notes):
print(self.header("%2d. %s") % (n+1, note))
- else:
- print("Use 'edit' to create a note.")
+ print("Use the 'edit' command to edit a note.")
+ print("Use the 'preview' command to look at a note.")
+ print("Use the 'post' command to post a note.")
+ print("Use the 'comment' command to post a comment.")
else:
- print("Things to list: notes.")
+ print("Use 'edit' to create a note.")
def get_notes(self):
"""Get the list of notes."""
"""Get the correct path for a note."""
return os.path.join(get_notes_dir(), filename)
+ def read_note(self, filename):
+ """Get text of a note."""
+ with open(self.get_note_path(filename), mode = 'r', encoding = 'utf-8') as fp:
+ return fp.read()
+
+ def do_preview(self, line):
+ """Preview a note using your pager.
+Use the 'pager' command to set your pager to something like 'mdcat'."""
+ if line == "":
+ print("The 'preview' command the number of a note as an argument.")
+ print("Use the 'notes' command to list all your notes.")
+ return
+ try:
+ n = int(line.strip())
+ notes = self.get_notes()
+ if notes:
+ try:
+ self.show(self.read_note(notes[n-1]))
+ except IndexError:
+ print("Use the 'list notes' command to list valid numbers.")
+ return
+ else:
+ print("There are no notes to preview.")
+ return
+ except ValueError:
+ print("The 'preview' command takes a number as its argument.")
+ return
+
+ def do_home(self, line):
+ """Show the main stream containing the combined posts of the
+followed users and tags and the community spotlights posts if
+the user enabled those."""
+ if line == "":
+ if self.home:
+ print("Redisplaying the cached statuses of the home stream.")
+ print("Use the 'reload' argument to reload them.")
+ print("Use the 'all' argument to show them all.")
+ print("Use a number to show only that many.")
+ print("The default is 5.")
+ else:
+ print("Loading...")
+ self.home = diaspy.streams.Stream(self.connection)
+ self.home.fill()
+ for post in self.home:
+ if post.id not in self.post_cache:
+ self.post_cache[post.id] = post
+ elif line == "reload":
+ if self.connection == None:
+ print("Use the 'login' command, first.")
+ return
+ if self.home:
+ print("Reloading...")
+ self.home.update()
+ line = ""
+ else:
+ self.home = diaspy.streams.Stream(self.connection)
+ self.home.fill()
+
+ n = 5
+ posts = sorted(self.home, key=lambda x: x.data()["created_at"])
+
+ if line == "all":
+ n = None
+ elif line != "":
+ try:
+ n = int(line.strip())
+ except ValueError:
+ print("The 'home' command takes a number as its argument, or 'reload' or 'all'.")
+ print("The default is to show the last 5 posts.")
+ return
+
+ if n == None:
+ start = 0
+ else:
+ # n is from the back
+ start = max(len(posts) - n, 0)
+
+ if posts:
+ for n, post in enumerate(posts[start:], start):
+ print()
+ print(self.header("%2d. %s %s") % (n+1, post.data()["created_at"], post.author()))
+ print()
+ self.show(post)
+
+ print("Enter a number to select the post.")
+ self.numbers_refer_to = 'home'
+ else:
+ print("The people you follow have nothing to say.")
+ print("The tags you follow are empty. 😢")
+
+ def do_shortcuts(self, line):
+ """List all shortcuts."""
+ if line != "":
+ print("The 'shortcuts' command does not take an argument.")
+ return
+ print(self.header("Shortcuts"))
+ for shortcut in sorted(shortcuts):
+ print("%s\t%s" % (shortcut, shortcuts[shortcut]))
+ print("Use the 'shortcut' command to change or add shortcuts.")
+
+ def do_shortcut(self, line):
+ """Define a new shortcut."""
+ words = line.strip().split(maxsplit = 1)
+ if len(words) == 0:
+ return self.onecmd("shortcuts")
+ elif len(words) == 1:
+ shortcut = words[0]
+ if shortcut in shortcuts:
+ print("%s\t%s" % (shortcut, shortcuts[shortcut]))
+ else:
+ print("%s is not a shortcut" % shortcut)
+ else:
+ shortcuts[words[0]] = words[1]
+
# Main function
def main():