Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/usability improvements #29

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,17 @@
[![Build Status](https://travis-ci.org/EneApp/Ene.svg?branch=master)](https://travis-ci.org/EneApp/Ene)
[![codecov](https://codecov.io/gh/EneApp/Ene/branch/master/graph/badge.svg)](https://codecov.io/gh/EneApp/Ene)
[![Maintainability](https://api.codeclimate.com/v1/badges/4864f2446db73847010e/maintainability)](https://codeclimate.com/github/EneApp/Ene/maintainability)

## About Ene

Ene is an anime library manager for Linux, macOS and Windows designed to track progress and organize your shows. It will keep a list of all known unique shows contained within your library in addition to the episodes you've watched. Automatic AniList synchronization is a planned feature.

## Getting Started

After first starting Ene you will be prompted to login to your AniList account.

After doing this, you can add folders to watch by going to Settings > Preferences > Local Files, and adding one or more directories to pull files from. Then you can refresh Ene's database of shows by clicking File > Refresh Library, this will pull in a list of all shows and all of their episodes for you to watch. You can configure your video player of choice in Preferences, vlc and mpv are currently supported, other video players are attempted by simply passing the file path as a command line parameter. If you're interested in support for another player, please consider logging an issue, or [contributing](./CONTRIBUTING.md)

## Contributing

See [CONTRIBUTING.md](./CONTRIBUTING.md)
2 changes: 1 addition & 1 deletion ene.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash
# ENE, Automatically track and sync anime watching progress
# Copyright (C) 2018-2020 Peijun Ma, Justin Sedge
# Copyright (C) 2018-2021 Peijun Ma, Justin Sedge
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down
2 changes: 1 addition & 1 deletion ene/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# ENE, Automatically track and sync anime watching progress
# Copyright (C) 2018-2020 Peijun Ma, Justin Sedge
# Copyright (C) 2018-2021 Peijun Ma, Justin Sedge
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down
2 changes: 1 addition & 1 deletion ene/__main__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# ENE, Automatically track and sync anime watching progress
# Copyright (C) 2018-2020 Peijun Ma, Justin Sedge
# Copyright (C) 2018-2021 Peijun Ma, Justin Sedge
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down
2 changes: 1 addition & 1 deletion ene/api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# ENE, Automatically track and sync anime watching progress
# Copyright (C) 2018-2020 Peijun Ma, Justin Sedge
# Copyright (C) 2018-2021 Peijun Ma, Justin Sedge
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down
204 changes: 153 additions & 51 deletions ene/api/anilist.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# ENE, Automatically track and sync anime watching progress
# Copyright (C) 2018-2020 Peijun Ma, Justin Sedge
# Copyright (C) 2018-2021 Peijun Ma, Justin Sedge
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand All @@ -26,7 +26,7 @@
from .auth import OAuth
from .enums import MediaFormat, MediaListStatus, MediaSeason, MediaSort, MediaStatus
from .media import Media
from .types_ import FuzzyDate
from .media_list import MediaList

HTTP_ERROR = Tuple[int, str]
API_RES = Result[Dict, HTTP_ERROR]
Expand All @@ -41,6 +41,7 @@ class API:
cache_home = attr.ib()
session = attr.ib(factory=Session, init=False)
token = attr.ib(init=False)
user_id = attr.ib(init=False, default=None)

def __attrs_post_init__(self):
self.token = OAuth.get_token(self.data_home, CLIENT_ID, '127.0.0.1', 50000)
Expand All @@ -50,6 +51,22 @@ def __attrs_post_init__(self):
'Accept': 'application/json'
})

def current_user(self):
"""
Returns the current user, does API lookup and caches if required

Returns:
The user id of the current user
"""
if not self.user_id:
user = self.get_current_user().map(lambda v: v['data']['Viewer']['id'])
print(user)
print(type(user))
print(user.unwrap())
print(type(user.unwrap()))
self.user_id = user.unwrap()
return self.user_id

def query(self, query: str, variables: Optional[dict] = None) -> API_RES:
"""
Makes HTTP request to the Anilist API
Expand Down Expand Up @@ -353,20 +370,71 @@ def get_show(self, show: str) -> Result[Media, HTTP_ERROR]:
variables = {
'title': show
}
return self.query(query, variables).map(lambda v: Media(v, self.cache_home))
return self.query(query, variables).map(lambda v: Media(v['data']['Media'],
self.cache_home))

def get_show_by_id(self, media_id: int) -> Result[Media, HTTP_ERROR]:
"""
Gets information about a single show by media id

Args:
media_id:
The AniList media ID to search for

Returns:
Information about the show
"""
query = """\
query ($id: Int) {
Media(id: $id, type: ANIME) {
id
coverImage {
large
medium
}
}
}"""
variables = {
'id': media_id
}
return self.query(query, variables).map(lambda v: Media(v['data']['Media'],
self.cache_home))

def get_shows(self, show: str):
"""
Looks up multiple Media entries for a given search name

Args:
show:
The show name to search for

Returns:
A list of matching show names and media ids
"""

query = """\
query ($showName: String) {
Page(perPage: 5) {
media(search: $showName, type: ANIME) {
id
title {
userPreferred
}
}
}
}"""
variables = {
'showName': show
}

return self.query(query, variables).map(lambda v: v['data']['Page']['media'])

def update_media_list_entry( # pylint: disable=R0913
self,
media_id: int,
status: Optional[MediaListStatus] = None,
score: Optional[float] = None,
progress: Optional[int] = None,
repeat: Optional[int] = None,
private: Optional[bool] = None,
notes: Optional[str] = None,
custom_lists: Optional[Dict[str, bool]] = None,
started_at: Optional[FuzzyDate] = None,
completed_at: Optional[FuzzyDate] = None,
progress: Optional[int] = None
) -> API_RES:
"""
Update a media list entry for the user.
Expand All @@ -376,12 +444,6 @@ def update_media_list_entry( # pylint: disable=R0913
status: The watching status
score: The score of the entry
progress: The amount of episodes consumed by the user
custom_lists: Map of booleans for which lists the entry are in
private: If the entry should only be visible to authenticated user
notes: Text notes
started_at: When the entry was started by the user
completed_at: When the entry was completed by the user
repeat: The amount of times the user has re-watched the media

Returns:
The updated media entry values.
Expand All @@ -391,56 +453,96 @@ def update_media_list_entry( # pylint: disable=R0913
$mediaId: Int,
$status: MediaListStatus,
$score: Float,
$progress: Int,
$customLists: Json,
$private: Boolean,
$notes: String,
$startedAt: FuzzyDate,
$completedAt: FuzzyDate,
$repeat: Int
$progress: Int
) {
SaveMediaListEntry (
mediaId: $mediaId,
status: $status,
score: $score,
progress: $progress,
customLists: $customLists,
private: $private,
notes: $notes,
startedAt: $startedAt,
completedAt: $completedAt,
repeat: $repeat
progress: $progress
) {
id
status
score
progress
repeat
private
notes
customLists
startedAt
completedAt
}
}"""
variables = dict_filter({
"mediaId": media_id,
"status": status.name if status else None,
"score": score,
"progress": progress,
"customLists": custom_lists,
"private": private,
"notes": notes,
"startedAt": {
"year": started_at.year,
"month": started_at.month,
"day": started_at.day
} if started_at else None,
"completedAt": {
"year": completed_at.year,
"month": completed_at.month,
"day": completed_at.day
} if completed_at else None,
"repeat": repeat,
"progress": progress
})
return self.query(query, variables)

def create_media_list_entry(self, media_id: int) -> MediaList:
query = """
mutation ($media_id: Int, $progress: Int, $status: MediaListStatus) {
SaveMediaListEntry (mediaId: $media_id, progress: $progress, status: $status) {
id
status
score
progress
mediaId
}
}
"""

variables = dict_filter({
"media_id": media_id,
"status": MediaListStatus.CURRENT.name,
"progress": 0
})

return self.query(query, variables).map(lambda res:
MediaList(res['data']['SaveMediaListEntry']))

def get_current_user(self):
query = """\
query User {
Viewer {
id
}
}
"""
return self.query(query)

def get_media_list_entry(self, media_id: int):
query = """
query ($user_id: Int!, $media_id: Int!) {
Page {
mediaList(userId: $user_id, type: ANIME, mediaId: $media_id) {
id
status
score
progress
mediaId
private
repeat
customLists
completedAt {
year
month
day
}
startedAt {
year
month
day
}
notes
}
}
}
"""
variables = dict_filter({
'user_id': self.current_user(),
'media_id': media_id
})

def _process_results(res):
for result in res['data']['Page']['mediaList']:
return MediaList(result)
return None

return self.query(query, variables).map(_process_results)
2 changes: 1 addition & 1 deletion ene/api/auth.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# ENE, Automatically track and sync anime watching progress
# Copyright (C) 2018-2020 Peijun Ma, Justin Sedge
# Copyright (C) 2018-2021 Peijun Ma, Justin Sedge
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down
2 changes: 1 addition & 1 deletion ene/api/enums.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# ENE, Automatically track and sync anime watching progress
# Copyright (C) 2018-2020 Peijun Ma, Justin Sedge
# Copyright (C) 2018-2021 Peijun Ma, Justin Sedge
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down
5 changes: 3 additions & 2 deletions ene/api/media.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# ENE, Automatically track and sync anime watching progress
# Copyright (C) 2018-2020 Peijun Ma, Justin Sedge
# Copyright (C) 2018-2021 Peijun Ma, Justin Sedge
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand All @@ -22,7 +22,8 @@

from ene.util import get_resource
from .enums import MediaFormat, MediaSeason, MediaStatus, MediaType
from .types_ import AiringEpisode, FuzzyDate, MediaList, Studio
from .media_list import MediaList
from .types_ import AiringEpisode, FuzzyDate, Studio


@attr.s(repr=False, slots=True, auto_attribs=True)
Expand Down
Loading