rssVideos: Sync read state
Deleted but previously downloaded = read
This commit is contained in:
parent
b0f14812d5
commit
c36534f696
|
@ -108,13 +108,15 @@ class RVElement:
|
||||||
parent: "RVDatabase"
|
parent: "RVDatabase"
|
||||||
item: dict
|
item: dict
|
||||||
downloaded_filepath: typing.Optional[str]
|
downloaded_filepath: typing.Optional[str]
|
||||||
watched: bool
|
|
||||||
|
|
||||||
def __init__(self, parent: "RVDatabase", item: dict) -> None:
|
def __init__(self, parent: "RVDatabase", item: dict) -> None:
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.item = item
|
self.item = item
|
||||||
self.downloaded_filepath = None
|
self.downloaded_filepath = None
|
||||||
self.watched = False
|
|
||||||
|
@property
|
||||||
|
def id(self) -> str:
|
||||||
|
return self.item["id"]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def title(self) -> str:
|
def title(self) -> str:
|
||||||
|
@ -142,10 +144,9 @@ class RVElement:
|
||||||
log.debug(f"From cache: {self}")
|
log.debug(f"From cache: {self}")
|
||||||
if cache.downloaded_filepath:
|
if cache.downloaded_filepath:
|
||||||
self.downloaded_filepath = cache.downloaded_filepath
|
self.downloaded_filepath = cache.downloaded_filepath
|
||||||
if cache.watched:
|
|
||||||
self.watched = True
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
|
# return self.item.get("id")
|
||||||
str = f"{self.guid}: {self.creator if self.creator else '?'} – {self.title}"
|
str = f"{self.guid}: {self.creator if self.creator else '?'} – {self.title}"
|
||||||
if self.is_researched:
|
if self.is_researched:
|
||||||
if self.is_video:
|
if self.is_video:
|
||||||
|
@ -232,6 +233,12 @@ class RVElement:
|
||||||
return
|
return
|
||||||
self.download()
|
self.download()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def watched(self) -> bool:
|
||||||
|
if not self.is_researched:
|
||||||
|
return False
|
||||||
|
return self.was_downloaded and not self.downloaded
|
||||||
|
|
||||||
def matches_filter(self, args: configargparse.Namespace) -> bool:
|
def matches_filter(self, args: configargparse.Namespace) -> bool:
|
||||||
# Inexpensive filters
|
# Inexpensive filters
|
||||||
if args.seen != "any" and (args.seen == "seen") != self.watched:
|
if args.seen != "any" and (args.seen == "seen") != self.watched:
|
||||||
|
@ -272,8 +279,8 @@ class RVElement:
|
||||||
proc = subprocess.run(cmd)
|
proc = subprocess.run(cmd)
|
||||||
proc.check_returncode()
|
proc.check_returncode()
|
||||||
|
|
||||||
self.watched = True
|
self.clean()
|
||||||
self.parent.save()
|
self.try_mark_read()
|
||||||
|
|
||||||
def clean(self) -> None:
|
def clean(self) -> None:
|
||||||
assert self.is_video
|
assert self.is_video
|
||||||
|
@ -284,6 +291,32 @@ class RVElement:
|
||||||
if not self.parent.args.dryrun:
|
if not self.parent.args.dryrun:
|
||||||
os.unlink(file)
|
os.unlink(file)
|
||||||
|
|
||||||
|
def mark_read(self) -> None:
|
||||||
|
log.debug(f"Marking {self} read")
|
||||||
|
if self.parent.args.dryrun:
|
||||||
|
return
|
||||||
|
r = requests.post(
|
||||||
|
f"{self.parent.args.url}/reader/api/0/edit-tag",
|
||||||
|
data={
|
||||||
|
"i": self.id,
|
||||||
|
"a": "user/-/state/com.google/read",
|
||||||
|
"ac": "edit",
|
||||||
|
"token": self.parent.feed_token,
|
||||||
|
},
|
||||||
|
headers=self.parent.auth_headers,
|
||||||
|
)
|
||||||
|
r.raise_for_status()
|
||||||
|
if r.text.strip() != "OK":
|
||||||
|
raise RuntimeError(f"Couldn't mark {self} as read: {r.text}")
|
||||||
|
log.info(f"Marked {self} as read")
|
||||||
|
self.parent.elements.remove(self)
|
||||||
|
|
||||||
|
def try_mark_read(self) -> None:
|
||||||
|
try:
|
||||||
|
self.mark_read()
|
||||||
|
except requests.ConnectionError:
|
||||||
|
log.warning(f"Couldn't mark {self} as read")
|
||||||
|
|
||||||
|
|
||||||
class RVDatabase:
|
class RVDatabase:
|
||||||
SAVE_FILE = ".cache.p"
|
SAVE_FILE = ".cache.p"
|
||||||
|
@ -478,6 +511,20 @@ class RVDatabase:
|
||||||
|
|
||||||
return elements
|
return elements
|
||||||
|
|
||||||
|
@functools.cached_property
|
||||||
|
def feed_token(self) -> str:
|
||||||
|
r = requests.get(
|
||||||
|
f"{self.args.url}/reader/api/0/token",
|
||||||
|
headers=self.auth_headers,
|
||||||
|
)
|
||||||
|
r.raise_for_status()
|
||||||
|
return r.text.strip()
|
||||||
|
|
||||||
|
def try_mark_watched_read(self) -> None:
|
||||||
|
for element in self.elements:
|
||||||
|
if element.watched:
|
||||||
|
element.try_mark_read()
|
||||||
|
|
||||||
|
|
||||||
def get_args() -> configargparse.Namespace:
|
def get_args() -> configargparse.Namespace:
|
||||||
defaultConfigPath = os.path.join(
|
defaultConfigPath = os.path.join(
|
||||||
|
@ -595,8 +642,6 @@ def get_args() -> configargparse.Namespace:
|
||||||
"watch",
|
"watch",
|
||||||
"binge",
|
"binge",
|
||||||
"clean",
|
"clean",
|
||||||
"seen",
|
|
||||||
"unseen",
|
|
||||||
),
|
),
|
||||||
default="download",
|
default="download",
|
||||||
)
|
)
|
||||||
|
@ -654,6 +699,7 @@ def main() -> None:
|
||||||
else:
|
else:
|
||||||
duration = 0
|
duration = 0
|
||||||
for element in database.filter(args):
|
for element in database.filter(args):
|
||||||
|
duration += element.duration if element.is_video else 0
|
||||||
if args.action == "download":
|
if args.action == "download":
|
||||||
element.preload()
|
element.preload()
|
||||||
elif args.action == "list":
|
elif args.action == "list":
|
||||||
|
@ -662,19 +708,11 @@ def main() -> None:
|
||||||
element.watch()
|
element.watch()
|
||||||
if args.action == "watch":
|
if args.action == "watch":
|
||||||
break
|
break
|
||||||
elif args.action == "seen":
|
|
||||||
if not element.watched:
|
|
||||||
log.info(f"Maked as seen: {element}")
|
|
||||||
element.watched = True
|
|
||||||
elif args.action == "unseen":
|
|
||||||
if element.watched:
|
|
||||||
log.info(f"Maked as unseen: {element}")
|
|
||||||
element.watched = False
|
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(f"Unimplemented action: {args.action}")
|
raise NotImplementedError(f"Unimplemented action: {args.action}")
|
||||||
duration += element.duration if element.is_video else 0
|
|
||||||
log.info(f"Total duration: {format_duration(duration)}")
|
log.info(f"Total duration: {format_duration(duration)}")
|
||||||
database.attempt_clean()
|
database.attempt_clean()
|
||||||
|
database.try_mark_watched_read()
|
||||||
database.save()
|
database.save()
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue