aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rwxr-xr-xtools/list-by-updated.sh10
-rwxr-xr-xtools/list-missing-unwatched.py50
-rwxr-xr-xtools/list-unwatched.py40
-rwxr-xr-xtools/open_media.py114
-rwxr-xr-xtools/track.py75
5 files changed, 289 insertions, 0 deletions
diff --git a/tools/list-by-updated.sh b/tools/list-by-updated.sh
new file mode 100755
index 0000000..61b9a0e
--- /dev/null
+++ b/tools/list-by-updated.sh
@@ -0,0 +1,10 @@
+#!/bin/sh -e
+
+for tracked_dir in ~/.config/automedia/rss/tracked/* ~/.config/automedia/html/tracked/*; do
+ cat "$tracked_dir/updated"
+ echo " " $(basename "$tracked_dir")
+done | sort -nr | while IFS= read -r line; do
+ timestamp=$(date -d @$(echo "$line" | cut -d' ' -f1))
+ tracked_item=$(echo "$line" | cut -d' ' -f2-)
+ echo "$timestamp" "|" "$tracked_item"
+done
diff --git a/tools/list-missing-unwatched.py b/tools/list-missing-unwatched.py
new file mode 100755
index 0000000..980c500
--- /dev/null
+++ b/tools/list-missing-unwatched.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python3
+
+import os
+import subprocess
+import sys
+
+def show_notification(title, description, urgency):
+ print("Notification: title: %s, description: %s" % (title, description))
+ process = subprocess.Popen(["notify-send", "-a", "automedia", "-t", "10000", "-u", urgency, "--", title, description])
+ stdout, stderr = process.communicate()
+ return process.returncode == 0
+
+def get_downloaded():
+ process = subprocess.Popen(["automedia", "downloaded"], stdout=subprocess.PIPE)
+ stdout, stderr = process.communicate()
+ if process.returncode != 0:
+ return None
+ return stdout.decode("utf-8").splitlines(False)
+
+def get_seen():
+ try:
+ with open(os.path.expanduser("~/.config/automedia/seen")) as file:
+ return file.read().splitlines()
+ except IOError as err:
+ return []
+
+def main():
+ if len(sys.argv) != 2:
+ print("usage: list-missing-unwatched.py <automedia-download-dir>")
+ sys.exit(1)
+
+ automedia_dir = sys.argv[1]
+ if not os.path.exists(automedia_dir):
+ show_notification("list-missing-unwatched", "No such file or directory: " % automedia_dir, "critical")
+ sys.exit(2)
+
+ downloaded = get_downloaded()
+ if not downloaded:
+ show_notification("list-missing-unwatched", "Failed to get downloaded episodes/chapters", "critical")
+ sys.exit(2)
+
+ downloaded = dict.fromkeys(downloaded)
+ seen = dict.fromkeys(get_seen())
+ unwatched = [t for t in downloaded if t not in seen]
+ missing = [u for u in unwatched if not os.path.exists(os.path.join(automedia_dir, u))]
+ for u in missing:
+ print(u)
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/list-unwatched.py b/tools/list-unwatched.py
new file mode 100755
index 0000000..874df7b
--- /dev/null
+++ b/tools/list-unwatched.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python3
+
+import os
+import subprocess
+
+def show_notification(title, description, urgency):
+ print("Notification: title: %s, description: %s" % (title, description))
+ process = subprocess.Popen(["notify-send", "-a", "automedia", "-t", "10000", "-u", urgency, "--", title, description])
+ stdout, stderr = process.communicate()
+ return process.returncode == 0
+
+def get_downloaded():
+ process = subprocess.Popen(["automedia", "downloaded"], stdout=subprocess.PIPE)
+ stdout, stderr = process.communicate()
+ if process.returncode != 0:
+ return None
+ return stdout.decode("utf-8").splitlines(False)
+
+def get_seen():
+ try:
+ with open(os.path.expanduser("~/.config/automedia/seen")) as file:
+ return file.read().splitlines()
+ except IOError as err:
+ return []
+
+def main():
+ downloaded = get_downloaded()
+ if not downloaded:
+ show_notification("list-unwatched", "Failed to get downloaded episodes/chapters", "critical")
+ sys.exit(2)
+
+ downloaded = dict.fromkeys(downloaded)
+ seen = dict.fromkeys(get_seen())
+ unwatched = [t for t in downloaded if t not in seen]
+
+ for u in unwatched:
+ print(u)
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/open_media.py b/tools/open_media.py
new file mode 100755
index 0000000..66d8ed7
--- /dev/null
+++ b/tools/open_media.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python3
+
+import os
+import sys
+import subprocess
+
+script_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
+
+def run_dmenu(input):
+ process = subprocess.Popen(["dmenu", "-l", "15", "-i", "-p", "Select media"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+ stdout, stderr = process.communicate(input.encode())
+ if process.returncode == 0:
+ return stdout
+ elif process.returncode != 1:
+ print("Failed to launch dmenu, error: {}".format(stderr))
+ return None
+
+def add_seen(seen_filepath, media_name, seen_list):
+ if media_name in seen_list:
+ return
+ with open(seen_filepath, "a") as seen_file:
+ seen_file.write(media_name + "\n")
+
+def sort_images(filename):
+ idx = filename.find(".")
+ if idx != -1:
+ return int(filename[0:idx])
+ return 0
+
+def get_downloaded_list():
+ process = subprocess.Popen(["automedia", "downloaded"], stdout=subprocess.PIPE)
+ stdout, stderr = process.communicate()
+ if process.returncode == 0:
+ return stdout.decode().splitlines()
+ else:
+ print("Failed to list downloaded items, error: {}".format(stderr))
+ return []
+
+def get_manga_chapters_in_dir(manga_dir):
+ files = []
+ for filename in os.listdir(manga_dir):
+ full_path = os.path.join(manga_dir, filename)
+ if os.path.isdir(full_path) and not os.path.exists(os.path.join(full_path, ".in_progress")):
+ files.append(full_path)
+ return files
+
+def get_files_in_download_dir(download_dir):
+ files_in_media_path = []
+ for filename in os.listdir(download_dir):
+ full_path = os.path.join(download_dir, filename)
+ if os.path.isdir(full_path):
+ files_in_media_path.extend(get_manga_chapters_in_dir(full_path))
+ if os.path.isfile(full_path):
+ files_in_media_path.append(full_path)
+ return files_in_media_path
+
+def main():
+ if len(sys.argv) < 2:
+ print("usage: open_media.py <download_dir>")
+ print("example: open_media.sh /home/user/Downloads/automedia")
+ exit(1)
+
+ download_dir = sys.argv[1]
+ if not os.path.isdir(download_dir):
+ print("No such directory: " % str(download_dir))
+ exit(2)
+
+ files_in_media_path = get_files_in_download_dir(download_dir)
+
+ downloaded_list = get_downloaded_list()
+ filtered_downloaded_list = []
+ for item in downloaded_list:
+ media_path = os.path.join(download_dir, item)
+ if media_path in files_in_media_path:
+ filtered_downloaded_list.append(item)
+
+ os.makedirs(os.path.expanduser("~/.config/automedia"), exist_ok=True)
+ seen_filepath = os.path.expanduser("~/.config/automedia/seen")
+ seen_list = []
+ try:
+ with open(seen_filepath, "r") as seen_file:
+ seen_list = seen_file.read().splitlines()
+ except OSError as e:
+ print("Failed to open {}, reason: {}".format(seen_filepath, str(e)))
+
+ for seen in seen_list:
+ for i, downloaded in enumerate(filtered_downloaded_list):
+ if seen == downloaded:
+ filtered_downloaded_list[i] = "✓ {}".format(downloaded)
+
+ selected_media = run_dmenu("\n".join(filtered_downloaded_list[::-1]))
+ if not selected_media:
+ exit(0)
+ selected_media = selected_media.decode().replace("✓ ", "").rstrip()
+
+ media_path = os.path.join(download_dir, selected_media)
+ if os.path.isdir(media_path):
+ add_seen(seen_filepath, selected_media, seen_list)
+ files = []
+ for filename in os.listdir(media_path):
+ if filename not in (".finished", ".session_id"):
+ files.append(filename)
+
+ files = sorted(files, key=sort_images)
+ process = subprocess.Popen(["sxiv", "-a", "-i"], stdin=subprocess.PIPE)
+ files_fullpath = []
+ for filename in files:
+ files_fullpath.append(os.path.join(media_path, filename))
+ process.communicate("\n".join(files_fullpath).encode())
+ elif os.path.isfile(media_path):
+ add_seen(seen_filepath, selected_media, seen_list)
+ subprocess.Popen(["mpv", "--", media_path])
+
+main()
diff --git a/tools/track.py b/tools/track.py
new file mode 100755
index 0000000..d56d8b3
--- /dev/null
+++ b/tools/track.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python3
+
+import os
+from pathlib import Path
+import subprocess
+import sys
+
+def show_notification(title, description, urgency):
+ print("Notification: title: %s, description: %s" % (title, description))
+ process = subprocess.Popen(["notify-send", "-a", "automedia", "-t", "10000", "-u", urgency, "--", title, description])
+ stdout, stderr = process.communicate()
+ return process.returncode == 0
+
+def get_tracked_episodes():
+ process = subprocess.Popen(["automedia", "downloaded", "--include-tracked"], stdout=subprocess.PIPE)
+ stdout, stderr = process.communicate()
+ if process.returncode != 0:
+ return None
+ return stdout.decode("utf-8").splitlines(False)
+
+def select_anime(anime_files):
+ process = subprocess.Popen(["dmenu", "-i", "-l", "15", "-p", "Select anime to track"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+ stdout, stderr = process.communicate(b"\n".join(anime_files))
+ if process.returncode != 0:
+ return None
+ return stdout.decode("utf-8").strip()
+
+def track_anime(anime):
+ add_process = subprocess.Popen(["automedia", "add", "rss", anime], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+
+ output = []
+ while True:
+ c = add_process.stdout.read(1)
+ if c == b':':
+ break
+ output.append(c)
+
+ submitter_prompt = b"".join(output).decode("utf-8")
+
+ dmenu_process = subprocess.Popen(["dmenu", "-i", "-l", "15", "-p", submitter_prompt], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+ stdout, stderr = dmenu_process.communicate(b"")
+ if dmenu_process.returncode != 0:
+ return None
+
+ chosen_submitter = stdout.decode("utf-8").strip()
+ add_process.communicate((chosen_submitter + "\n" + "\n").encode("utf-8"))
+ return add_process.returncode == 0
+
+def main():
+ if len(sys.argv) != 2:
+ print("usage: track.py <anime-dir>")
+ sys.exit(1)
+
+ anime_dir = sys.argv[1]
+ all_files = sorted(Path(anime_dir).iterdir(), key=os.path.getmtime, reverse=True)
+ anime_files = [os.path.basename(filepath).encode("utf-8") for filepath in all_files if os.path.isfile(filepath)]
+
+ tracked_episodes = get_tracked_episodes()
+ if not tracked_episodes:
+ show_notification("Track anime", "Failed to get tracked episodes", "critical")
+ sys.exit(1)
+
+ tracked_episodes_set = set(tracked_episodes)
+ anime_files = [anime_file for anime_file in anime_files if anime_file.decode("utf-8") not in tracked_episodes_set]
+
+ selected_anime = select_anime(anime_files)
+ if not selected_anime:
+ sys.exit(0)
+
+ if not track_anime(selected_anime):
+ show_notification("Track anime", "Failed to track %s" % selected_anime, "critical")
+ sys.exit(1)
+
+if __name__ == "__main__":
+ main()