diff options
-rw-r--r-- | config.py | 2 | ||||
-rw-r--r-- | database.py | 4 | ||||
-rw-r--r-- | interface.py | 20 | ||||
-rw-r--r-- | jellyfin.py | 25 |
4 files changed, 24 insertions, 27 deletions
@@ -14,7 +14,7 @@ def read_config_file(): | |||
14 | return parser | 14 | return parser |
15 | 15 | ||
16 | 16 | ||
17 | def write_config_file(parser): | 17 | def write_config_file(parser:ConfigParser): |
18 | """ Write ConfigParser contents back to config file """ | 18 | """ Write ConfigParser contents back to config file """ |
19 | with open(os.path.expanduser(CONFIG_FILE), "w") as conf: | 19 | with open(os.path.expanduser(CONFIG_FILE), "w") as conf: |
20 | parser.write(conf) | 20 | parser.write(conf) |
diff --git a/database.py b/database.py index 1c5304c..039a893 100644 --- a/database.py +++ b/database.py | |||
@@ -27,7 +27,7 @@ class Database(object): | |||
27 | )""") | 27 | )""") |
28 | 28 | ||
29 | 29 | ||
30 | def query_playstate(self, item_id): | 30 | def query_playstate(self, item_id:str): |
31 | """ Gets the playstate data for a given item id """ | 31 | """ Gets the playstate data for a given item id """ |
32 | with sqlite3.connect(self.path) as conn: | 32 | with sqlite3.connect(self.path) as conn: |
33 | c = conn.cursor() | 33 | c = conn.cursor() |
@@ -39,7 +39,7 @@ class Database(object): | |||
39 | return playstate | 39 | return playstate |
40 | 40 | ||
41 | 41 | ||
42 | def update_playstate(self, item_id, pct_played, sec_played): | 42 | def update_playstate(self, item_id:str, pct_played:float, sec_played:int): |
43 | """ Updates the playstate of a given item id """ | 43 | """ Updates the playstate of a given item id """ |
44 | with sqlite3.connect(self.path) as conn: | 44 | with sqlite3.connect(self.path) as conn: |
45 | c = conn.cursor() | 45 | c = conn.cursor() |
diff --git a/interface.py b/interface.py index 5d3ff24..817e7b1 100644 --- a/interface.py +++ b/interface.py | |||
@@ -130,7 +130,7 @@ class Interface: | |||
130 | 130 | ||
131 | def build(self): | 131 | def build(self): |
132 | """ Build urwid/curses UI """ | 132 | """ Build urwid/curses UI """ |
133 | self.header = urwid.AttrWrap(urwid.Text("joc"), "header") | 133 | self.header = urwid.AttrWrap(urwid.Text("Main Mode"), "header") |
134 | self.content = urwid.SimpleFocusListWalker([]) | 134 | self.content = urwid.SimpleFocusListWalker([]) |
135 | self.body = urwid.ListBox(self.content) | 135 | self.body = urwid.ListBox(self.content) |
136 | self.display_contents = self.libs | 136 | self.display_contents = self.libs |
@@ -163,11 +163,11 @@ class Interface: | |||
163 | sys.exit(0) | 163 | sys.exit(0) |
164 | 164 | ||
165 | 165 | ||
166 | def keypress(self, key): | 166 | def keypress(self, key:str): |
167 | """ Handle a key press by the user """ | 167 | """ Handle a key press by the user """ |
168 | if self.ui_main.get_focus() == "body": | 168 | if self.ui_main.get_focus() == "body": |
169 | if key == 'h' or key == 'left': | 169 | if key == 'h' or key == 'left': |
170 | if not self.search_mode: | 170 | if not self.search_mode and not self.info_mode: |
171 | self.shift_left() | 171 | self.shift_left() |
172 | self.clear_buffer() | 172 | self.clear_buffer() |
173 | elif key == 'enter': | 173 | elif key == 'enter': |
@@ -188,7 +188,7 @@ class Interface: | |||
188 | self.content.set_focus(self.focus) | 188 | self.content.set_focus(self.focus) |
189 | self.clear_buffer() | 189 | self.clear_buffer() |
190 | elif key == 'l'or key == 'right': | 190 | elif key == 'l'or key == 'right': |
191 | if not self.search_mode: | 191 | if not self.search_mode and not self.info_mode: |
192 | self.shift_right() | 192 | self.shift_right() |
193 | self.clear_buffer() | 193 | self.clear_buffer() |
194 | elif key == 'i': | 194 | elif key == 'i': |
@@ -422,9 +422,9 @@ class Interface: | |||
422 | self.display_contents = content | 422 | self.display_contents = content |
423 | 423 | ||
424 | if self.info_mode: | 424 | if self.info_mode: |
425 | content = content[0].split("\n") | ||
425 | for line in content: | 426 | for line in content: |
426 | self.content.append(urwid.AttrWrap( | 427 | self.content.append(urwid.AttrWrap(urwid.Text(line), 'text')) |
427 | urwid.Text(line), 'text','focus')) | ||
428 | self.content.set_focus(0) | 428 | self.content.set_focus(0) |
429 | return | 429 | return |
430 | 430 | ||
@@ -468,7 +468,7 @@ class Interface: | |||
468 | self.content.set_focus(self.focus) | 468 | self.content.set_focus(self.focus) |
469 | 469 | ||
470 | 470 | ||
471 | def is_media(self, item): | 471 | def is_media(self, item:dict): |
472 | """ Determines if an item is a piece of media (as opposed to a container) | 472 | """ Determines if an item is a piece of media (as opposed to a container) |
473 | and returns a boolean. Determination is made by 'Type' field in Jellyfin | 473 | and returns a boolean. Determination is made by 'Type' field in Jellyfin |
474 | item JSON. """ | 474 | item JSON. """ |
@@ -593,7 +593,7 @@ class Interface: | |||
593 | 593 | ||
594 | 594 | ||
595 | 595 | ||
596 | def get_playstate(self, item_id): | 596 | def get_playstate(self, item_id:str): |
597 | DB_ITEMID_INDEX = 0 | 597 | DB_ITEMID_INDEX = 0 |
598 | DB_PCT_INDEX = 1 | 598 | DB_PCT_INDEX = 1 |
599 | DB_SEC_INDEX = 2 | 599 | DB_SEC_INDEX = 2 |
@@ -602,7 +602,7 @@ class Interface: | |||
602 | playstate = self.db.query_playstate(item_id) | 602 | playstate = self.db.query_playstate(item_id) |
603 | return playstate[DB_PCT_INDEX],playstate[DB_SEC_INDEX] | 603 | return playstate[DB_PCT_INDEX],playstate[DB_SEC_INDEX] |
604 | 604 | ||
605 | def set_playstate(self, item_id, pct_played, sec_played): | 605 | def set_playstate(self, item_id:str, pct_played:str, sec_played:str): |
606 | """ Updates playstate in local db of an item """ | 606 | """ Updates playstate in local db of an item """ |
607 | pct_played = float(pct_played) | 607 | pct_played = float(pct_played) |
608 | sec_played = int(sec_played) | 608 | sec_played = int(sec_played) |
@@ -623,4 +623,4 @@ class Interface: | |||
623 | focus_item = self.display_contents[self.focus] | 623 | focus_item = self.display_contents[self.focus] |
624 | 624 | ||
625 | info = self.jellyfin.get_info(focus_item["Id"]) | 625 | info = self.jellyfin.get_info(focus_item["Id"]) |
626 | self.display(info) | 626 | self.display([info]) |
diff --git a/jellyfin.py b/jellyfin.py index 007dccf..05c020a 100644 --- a/jellyfin.py +++ b/jellyfin.py | |||
@@ -13,6 +13,7 @@ import threading | |||
13 | import subprocess | 13 | import subprocess |
14 | import ssl | 14 | import ssl |
15 | import shlex | 15 | import shlex |
16 | from configparser import ConfigParser | ||
16 | 17 | ||
17 | APP_NAME = "joc" | 18 | APP_NAME = "joc" |
18 | CLIENT_VERSION = "0.01" | 19 | CLIENT_VERSION = "0.01" |
@@ -38,7 +39,7 @@ def die(msg): | |||
38 | 39 | ||
39 | class JellyfinConnection(object): | 40 | class JellyfinConnection(object): |
40 | 41 | ||
41 | def __init__(self, parser): | 42 | def __init__(self, parser:ConfigParser): |
42 | 43 | ||
43 | self.parser = parser | 44 | self.parser = parser |
44 | 45 | ||
@@ -96,7 +97,7 @@ class JellyfinConnection(object): | |||
96 | warnings.filterwarnings("ignore") | 97 | warnings.filterwarnings("ignore") |
97 | return client | 98 | return client |
98 | 99 | ||
99 | def login(self, server, username, password): | 100 | def login(self, server:str, username:str, password:str): |
100 | """ Login to Jellyfin server with JellyfinClient instance """ | 101 | """ Login to Jellyfin server with JellyfinClient instance """ |
101 | 102 | ||
102 | client = self.client_factory() | 103 | client = self.client_factory() |
@@ -126,7 +127,7 @@ class JellyfinConnection(object): | |||
126 | folders = self.api.get_media_folders()["Items"] | 127 | folders = self.api.get_media_folders()["Items"] |
127 | return sorted(folders,key=lambda folder: folder["Name"]) | 128 | return sorted(folders,key=lambda folder: folder["Name"]) |
128 | 129 | ||
129 | def get_children(self,parent_id): | 130 | def get_children(self,parent_id:str): |
130 | """ Get children of a given parent_id. | 131 | """ Get children of a given parent_id. |
131 | Sorts by date created if items are videos or by name otherwise. | 132 | Sorts by date created if items are videos or by name otherwise. |
132 | Returns the sotrted list """ | 133 | Returns the sotrted list """ |
@@ -143,7 +144,7 @@ class JellyfinConnection(object): | |||
143 | 144 | ||
144 | return children | 145 | return children |
145 | 146 | ||
146 | def get_previous(self,item_id): | 147 | def get_previous(self,item_id:str): |
147 | """Gets items that were shown on the previous screen, i.e. | 148 | """Gets items that were shown on the previous screen, i.e. |
148 | the parent item's siblings, i.e. the children of the grandparent item """ | 149 | the parent item's siblings, i.e. the children of the grandparent item """ |
149 | 150 | ||
@@ -158,7 +159,7 @@ class JellyfinConnection(object): | |||
158 | return self.get_children(grandparent["Id"]) | 159 | return self.get_children(grandparent["Id"]) |
159 | 160 | ||
160 | 161 | ||
161 | def get_parent(self,item_id): | 162 | def get_parent(self,item_id:str): |
162 | """ Get parent (first ancestor) of a given item """ | 163 | """ Get parent (first ancestor) of a given item """ |
163 | 164 | ||
164 | PARENT_INDEX = 0 | 165 | PARENT_INDEX = 0 |
@@ -166,7 +167,7 @@ class JellyfinConnection(object): | |||
166 | parent = ancestors[PARENT_INDEX] | 167 | parent = ancestors[PARENT_INDEX] |
167 | return parent | 168 | return parent |
168 | 169 | ||
169 | def search(self, term): | 170 | def search(self, term:str): |
170 | """ Search for a given term and return a alphabetically sorted list """ | 171 | """ Search for a given term and return a alphabetically sorted list """ |
171 | 172 | ||
172 | items = self.api.search_media_items(term,MEDIA_TYPES,None)["Items"] | 173 | items = self.api.search_media_items(term,MEDIA_TYPES,None)["Items"] |
@@ -178,25 +179,21 @@ class JellyfinConnection(object): | |||
178 | string representation of the item """ | 179 | string representation of the item """ |
179 | 180 | ||
180 | item = self.api.get_item(item_id) | 181 | item = self.api.get_item(item_id) |
181 | return json.dumps(item,indent=4) | 182 | return json.dumps(item,indent=2) |
182 | 183 | ||
183 | def mark_watched(self, item_id, watched=True): | 184 | def mark_watched(self, item_id:str, watched=True): |
184 | """ Mark an item as watched or unwatched""" | 185 | """ Mark an item as watched or unwatched""" |
185 | self.api.item_played(item_id, watched) | 186 | self.api.item_played(item_id, watched) |
186 | 187 | ||
187 | def mark_favorite(self, item_id, favorite=True): | 188 | def mark_favorite(self, item_id:str, favorite=True): |
188 | """ Mark an item as a favorite or unfavorite the item""" | 189 | """ Mark an item as a favorite or unfavorite the item""" |
189 | self.api.favorite(item_id, favorite) | 190 | self.api.favorite(item_id, favorite) |
190 | 191 | ||
191 | def get_url(self, item_id): | 192 | def get_url(self, item_id:str): |
192 | """ Get download URL of the selected media item """ | 193 | """ Get download URL of the selected media item """ |
193 | url = self.api.download_url(item_id) | 194 | url = self.api.download_url(item_id) |
194 | return url | 195 | return url |
195 | 196 | ||
196 | def set_played_progress(self, item:dict, ticks): | ||
197 | item["UserData"]["PlaybackPositionTicks"] = int(ticks) | ||
198 | res = self.api.session_progress(item) | ||
199 | |||
200 | 197 | ||
201 | if __name__ == '__main__': | 198 | if __name__ == '__main__': |
202 | main() | 199 | main() |