Compare commits

..

77 Commits

Author SHA1 Message Date
211850c85f New encryption (#21)
* new encryption for animixplay direct links

fix increment char for uppercase letters

* apply fixes
2022-11-14 22:07:14 -08:00
06d3ad3ff2 update provider ordering 2022-10-21 22:46:12 -07:00
3117738f27 update highlighting and play first episode automatically (#20) 2022-10-13 22:07:24 -07:00
64d70c34f2 update gogoanime url 2022-10-13 17:47:42 -07:00
d9d7549553 Fix menu showing after completing download(s) 2022-10-08 13:54:00 -07:00
5804f84f83 fix streaming menu (#19) 2022-10-06 20:41:15 -07:00
fd954e7ede Add episode selection param (#18)
* fix quality selection

* add episode selection argument

* fix quality selection menu appearing when flag not set

* fix episode selection appearing when no episodes released yet

* update readme

* update readme

* make selected quality the default if watching/downloading multiple episodes
2022-10-06 20:17:48 -07:00
da45bf15fe fix ordering of declarations 2022-09-13 17:56:45 -07:00
b3f1dea8ab update providers (#16)
* update providers list and fix mp4 quality selection

* cleanup code and update download function

* update scraping logic
2022-09-10 11:17:00 -07:00
2c7789c58f fix duplicate search results (#15) 2022-07-29 22:53:56 -07:00
2bab68a887 add menu and option for selecting provider to scrape (#14) 2022-07-19 00:10:38 -07:00
df82425eae update readme images 2022-07-14 00:02:08 -07:00
b92dd11fe6 move play from file and db functions into own files (#13)
* move play from file and db functions into own files
2022-07-13 23:40:19 -07:00
c384c93147 switch to axel instead of aria2c (#12) 2022-07-11 16:52:30 -07:00
fa108d860f fix multiword searches from menu (#11) 2022-07-11 12:30:27 -07:00
1c8afc16cc fix infinite loop on no results found 2022-07-10 05:26:30 -07:00
e8054c6cf2 update table definitions 2022-06-27 00:41:04 -07:00
bd949bb7c7 update to v3 functions (#8)
* update to v3 functions

* fix progress prompt appearing in rofi menus

* modularize UI in ani-cli for rofi vs cli
2022-06-26 21:38:28 -07:00
737d54bcd2 fix episode selection menu on anime with 0- episodes 2022-06-25 16:55:25 -07:00
7d574f7a6f fix theme not being passed properly in all cases 2022-06-16 23:35:35 -07:00
7ad12b0da8 squash more bugs 2022-06-12 21:51:53 -07:00
c7911dc0a7 squash some bugs 2022-06-12 21:33:12 -07:00
92b10cc0f6 update readme 2022-06-12 21:20:15 -07:00
e9c2048076 update readme 2022-06-12 19:18:38 -07:00
acdcf05514 cleanup code 2022-06-12 19:02:15 -07:00
ec41f5abb3 fix parsing of autoplay and silent mode flags 2022-06-12 19:00:03 -07:00
af7dee7d85 update cli flag parsing and cleanup code 2022-06-12 18:52:26 -07:00
822e40074c revert changes 2022-06-12 18:36:30 -07:00
80682a26db update cli flag parsing and cleanup code 2022-06-12 18:29:35 -07:00
4828923abb Add option to browse recently updated anime (#6)
* add recently updated anime option

* update aniwrapper menu ordering and increase columns to 2

* replace hardcoded base_url with variable
2022-06-12 00:00:37 -07:00
ba6c302022 Merge pull request #5 from ksyasuda/autoplay
add autoplay
2022-06-04 20:37:21 -07:00
f218b34e21 make autoplay stop after last episode 2022-06-04 16:37:55 -07:00
e5772469c7 update docs 2022-06-04 16:24:06 -07:00
2e53ac3bfc cleanup code 2022-06-04 16:24:02 -07:00
8d6acddea6 make yes default option autoplay prompt 2022-06-04 14:26:36 -07:00
870920cbf5 move anime_id from prompt to message in rofi prompt 2022-06-04 14:13:24 -07:00
1b797bee3e add autoplay flag for continue watching prompt after each episode 2022-06-04 02:05:37 -07:00
692301d893 add disclaimer 2022-05-18 22:23:32 -07:00
77eaa9e4b0 implement log access time fix 2022-05-05 16:59:27 -07:00
ce83a6155b fix same episode playing 2022-05-03 20:36:02 -07:00
73e6b8d181 add alternate link feature from main script 2022-05-02 17:19:05 -07:00
6dd2b4c279 update watch history highlighting when there is an episode 0 2022-04-25 19:49:05 -07:00
04476f3ba4 allow autoselecting episode 0 2022-04-25 19:39:22 -07:00
d061438e2e allow episode 0 2022-04-25 19:30:38 -07:00
505e5125b9 update link parsing 2022-04-19 13:01:47 -07:00
9322d028f8 Merge branch 'master' of github.com:ksyasuda/aniwrapper 2022-04-18 09:44:59 -07:00
0892bb1845 fix decryption alg again 2022-04-18 09:42:00 -07:00
ae0c19b5f2 add m3u8 quality parsing and fix mp4 quality parsing 2022-04-17 18:43:14 -07:00
13635cabf2 update decryption alg 2022-04-17 18:13:40 -07:00
d7e78836a4 add dynamic keys parsing code from main script 2022-04-15 22:18:18 -07:00
7c8a13573b new encryption keys 2022-04-15 04:36:43 -07:00
2f0f552068 update keys 2022-04-14 08:40:45 -07:00
47f9ca19ae refactor stream function to match check_db return code 2022-04-08 00:54:20 -07:00
acb236ce23 auto select episode if only one exists 2022-04-07 01:18:46 -07:00
fd59f7e2fe fix downloading an episode from menu 2022-04-03 13:43:09 -07:00
925b7c86e2 fix no search results found loop if no query provided 2022-04-03 11:59:16 -07:00
aa821e774a update readme 2022-04-02 16:27:51 -07:00
73eb2a274e implement some ani-cli V2 functions 2022-04-02 14:36:39 -07:00
6af4a46b86 clean up code a bit 2022-03-31 20:04:07 -07:00
cee96ec9cc monkey see monkey do 2022-03-29 17:45:32 -07:00
1d1dc517f4 fix episode naming for m3u8 download 2022-03-27 23:37:09 -07:00
0ea84fb450 fix episode naming for aria2c download 2022-03-26 11:56:37 -07:00
8327afc43e add ffmpeg as dependency 2022-03-15 16:41:01 -07:00
c7fb101b10 add ffmpeg for m3u8 download and update cryptography 2022-03-15 15:09:50 -07:00
228c2014c7 remove support for mplayer 2022-03-03 23:54:59 -08:00
006fdc6572 update episode selection prompt in command line mode 2022-03-03 23:46:52 -08:00
3c4189e3ac add resume function to command-line download mode 2022-03-03 23:42:48 -08:00
5c7093daf0 fix bug in interactive mode 2022-03-03 23:35:47 -08:00
776c4961aa update help/docs 2022-03-03 18:57:18 -08:00
aac3761e37 add -r flag to select previously watched anime and start at ep selection 2022-03-03 18:53:23 -08:00
aa39625956 port over new decrypt function to fix scraping issue 2022-03-03 18:04:20 -08:00
4af41db0bf add openssl to dep_ch function 2022-02-22 08:30:57 -08:00
8882405c0e add option to download current episode 2022-02-22 08:18:14 -08:00
4d704d4b32 make queries not distinct since uniqueness is enforced at table level 2022-02-21 19:41:50 -08:00
7a3a61bb58 run insert queries in background before search_eps function 2022-02-20 20:00:25 -08:00
f95ae51af8 check exit code directly in update_date function 2022-02-20 19:57:40 -08:00
8fb570b003 simplify logic in find_media function 2022-02-20 19:11:14 -08:00
13 changed files with 1339 additions and 858 deletions

View File

@ -73,7 +73,7 @@ episode introduction by skipping to the next moment of silence in the video
These are the minimum dependences required to run `aniwrapper`
```
aria2 curl grep mpv rofi sed sqlite3
axel curl ffmpeg grep mpv rofi sed sqlite3
```
**Arch Linux**
@ -92,10 +92,10 @@ Install the Dependencies
```sh
# Arch
pacman -S --needed aria2 curl grep mpv rofi sed sqlite3
pacman -S --needed axel curl ffmpeg grep mpv rofi sed sqlite3
# Debian
apt install aria2 curl grep mpv rofi sed sqlite3
apt install axel curl ffmpeg grep mpv rofi sed sqlite3
```
Clone and switch into the repo directory
@ -145,20 +145,19 @@ aniwrapper -c # Use ani-cli command-line mode (rofi disabled)
aniwrapper -C # Connect to history database
aniwrapper -d # Download anime in command-line mode
aniwrapper -d <query> # Run in download mode (best quality), searching for <query>
aniwrapper -e <episode> or <begin_episode - end_episode>
aniwrapper -f <starting_directory> # Specify starting directory for play_from_file mode, bypassing main menu
aniwrapper -h # Show help menu
aniwrapper -p # Enable player selection menu
aniwrapper -q # Launch menu with quality selection
aniwrapper -Q <query> # Query the history database
aniwrapper -r # Launch aniwrapper in quick-resume mode (start script on episode selection for the most recently streamed anime)
aniwrapper -S # Enable silent mode (suppress output to stdout) [cannot be used with -v]
aniwrapper -t <theme> # Choose rofi theme from presets
aniwrapper -T <path_to_config> # Specify custom rofi config
aniwrapper -v # Enable verbose logging
```
> Half-episodes (ex. saihate-no-paladin episode 7.5) are selectable, however they will not show up in the episodes list.
> To select half episodes add 'h' to the beginning for episodes like '7.5' -> 'h7' to select saihate-no-paladin episode 7.5
See [aniwrapper menus](docs/aniwrapper-menus.md) for more information about the menus used in the following options
### Option 1: Streaming
@ -209,7 +208,22 @@ The continue option queries the `sqlite3` history databse and pulls the list of
</details>
### Option 4: Play from File
### Option 4: Recently Updated Anime
This option will present the name and episode number of 30 recently updated anime on gogoanime
<details>
<summary>Example</summary>
<div align="center">
![example](https://thumbor.sudacode.com/svHFsX6ti3HZey32mX8uvEAjsLs=/600x0/smart/https%3A%2F%2Fthumbor.sudacode.com%2Fimage%2F395af378c5c44e0c9d45b0a44ea072ed%2Faniwrapper-recently-updated)
</div>
</details>
### Option 5: Play from File
<details>
@ -223,7 +237,7 @@ The continue option queries the `sqlite3` history databse and pulls the list of
</details>
### Option 5: Sync History
### Option 6: Sync History
This option allows you to sync your search/watch history across devices. It queries the database on the remote machine and inserts/updates the necessary rows
@ -233,7 +247,7 @@ At the moment, the requirements are as follows:
- The username must be the same across both devices
- The `history.sqlite3` file must be in the default location: `$XDG_CONFIG_HOME/aniwrapper/history.sqlite3`
### Option 6: Choose Theme
### Option 7: Choose Theme
Change aniwrapper theme
@ -249,49 +263,20 @@ Change aniwrapper theme
</details>
## ani-cli
```
# watch anime
ani-cli <query>
# verbose logging
ani-cli -v
# download anime
ani-cli -d <download_directory>
# resume watching anime
ani-cli -H
# sync history across devices
ani-cli -s
# choose quality
ani-cli -q <best (default)|1080p|720p|480p|360p|worst>
# choose rofi theme from presets
ani-cli -t <aniwrapper (default)|dracula|fancy|flamingo|material|nord|onedark>
# Specify starting directory for play_from_file mode (does not work with -c)
ani-cli -f <starting_directory>
# run ani-cli in command-line mode (rofi disabled)
ani-cli -c
```
# Themes
<div align="center">
Default theme
![aniwrapper main menu](https://imgur.com/HFq5gCq.png)
![aniwrapper main menu](https://thumbor.sudacode.com/cQTsFEWsSDLk4uxDXDEzLZ6iz5A=/800x0/smart/https%3A%2F%2Flychee.sudacode.com%2Fuploads%2Fbig%2Fe88fd7df7ccb5f626ee8200491034ae1.png)
| | |
| :---------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------: |
| <details><summary>doom-one</summary> ![doomone](https://imgur.com/zMU0i8l.png) </details> | <details><summary>dracula</summary> ![dracula](https://imgur.com/BPdIuX3.png)</details> |
| <details><summary>fancy</summary>![fancy](https://imgur.com/CZx73NL.png)</details> | <details><summary>material</summary>![material](https://imgur.com/eTWkxw2.png)</details> |
| <details><summary>onedark</summary>![onedark](https://imgur.com/rchqtBm.png)</details> | <details><summary>flamingo (sidebar theme)</summary>![flamingo-theme](https://imgur.com/pxF7hRE.png)</details> |
| | |
| :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <details><summary>alter</summary> ![alter](https://thumbor.sudacode.com/0tuoFHdJSX-ngb1821RITEAd_CQ=/800x0/smart/https%3A%2F%2Flychee.sudacode.com%2Fuploads%2Fbig%2Feb491f4d017fff38e52adcc0549ae6df.png) </details> | <details><summary>aniwrapper</summary> ![aniwrapper](https://thumbor.sudacode.com/cQTsFEWsSDLk4uxDXDEzLZ6iz5A=/800x0/smart/https%3A%2F%2Flychee.sudacode.com%2Fuploads%2Fbig%2Fe88fd7df7ccb5f626ee8200491034ae1.png) </details> |
| <details><summary>doom-one</summary> ![doomone](https://thumbor.sudacode.com/6BI7O7v9wR6ALeE4wL9uL26peT0=/800x0/smart/https%3A%2F%2Flychee.sudacode.com%2Fuploads%2Fbig%2F7d496a3208c892717c99be5bc1c84105.png) </details> | <details><summary>dracula</summary> ![dracula](https://thumbor.sudacode.com/L9R0wutce1Le5euJ0oinduMaXo4=/800x0/smart/https%3A%2F%2Flychee.sudacode.com%2Fuploads%2Fbig%2F9b8b8cc5e4cde8f76c39e4ab83cda6a3.png)</details> |
| <details><summary>fancy</summary>![fancy](https://thumbor.sudacode.com/mv1t2d3dPyRTwc1IIajoHZq6vnI=/800x0/smart/https%3A%2F%2Flychee.sudacode.com%2Fuploads%2Fbig%2Fd12f56fd513c5083f8e7316145ad5436.png)</details> | <details><summary>material</summary>![material](https://thumbor.sudacode.com/oOR41ZN6Cguch5oU2f9zDtdFyZc=/800x0/smart/https%3A%2F%2Flychee.sudacode.com%2Fuploads%2Fbig%2F40a1f13fc77b4ae8b75b082268e10391.png)</details> |
| <details><summary>monokai</summary>![monokai](https://thumbor.sudacode.com/ff1i68B4KlWsbVuN0s11eL_SXBI=/800x0/smart/https%3A%2F%2Flychee.sudacode.com%2Fuploads%2Fbig%2Fd9e8cec045948a2c32c9c7126da86294.png)</details> | <details><summary>nord</summary>![nord](https://thumbor.sudacode.com/l6wzDKIHbTpURbTX414BscTGlGg=/800x0/smart/https%3A%2F%2Flychee.sudacode.com%2Fuploads%2Fbig%2F636fbfea8aa40f10a9dd4d592015c58a.png)</details> |
| <details><summary>nord2</summary>![nord2](https://thumbor.sudacode.com/TTeXKVJpU75rT0Xe5Towmroc6Eo=/800x0/smart/https%3A%2F%2Flychee.sudacode.com%2Fuploads%2Fbig%2Fc358c9ca95aacb05bfad69b6b175db0c.png)</details> | <details><summary>onedark</summary>![onedark](https://thumbor.sudacode.com/ta8X8qGjH9to-_6-IDHHrOFpysM=/800x0/smart/https%3A%2F%2Flychee.sudacode.com%2Fuploads%2Fbig%2Fa1801ece1de4b981e68aaeca7a9b93f7.png)</details> |
</div>

1026
ani-cli

File diff suppressed because it is too large Load Diff

View File

@ -2,20 +2,18 @@
set -Eeo pipefail
#############
# Globals #
#############
CMD="/usr/bin/ani-cli"
CFG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/aniwrapper"
CFG_FILE="$CFG_DIR/themes/aniwrapper.rasi"
DEFAULT_DOWNLOAD="$HOME/Videos/sauce"
ROFI_THEME="aniwrapper.rasi"
THEMES="alter|aniwrapper|dracula|doomone|fancy|material|monokai|nord|nord2|onedark"
QUALITIES="1. best|2. 1080p|3. 720p|4. 480p|5. 360p|6. worst"
SUPPORTED_PLAYERS="mpv|mplayer|vlc"
QUALITIES="1. best|2. worst"
SUPPORTED_PLAYERS="mpv|vlc"
QUALITY=best
PLAYER_FN=mpv
DPI=96
IS_AUTOPLAY=0
GET_QUALITY=0
IS_CUSTOM_THEME=0
IS_DOWNLOAD=0
@ -23,35 +21,38 @@ IS_PLAY_FROM_FILE=0
IS_ROFI=1
IS_SYNC=0
IS_ALTERNATE_PLAYER=0
VERBOSE=0
IS_VERBOSE=0
IS_SELECT_EPISODE=1
SELECT_PROVIDER=0
SILENT=0
quit="7. Quit"
options="1. Stream|2. Download|3. Continue|4. Play from File|5. Sync History|6. Choose Theme|$quit"
quit="8. Quit"
options="1. Stream|2. Download|3. Continue|4. Recently Updated|5. Play from File|6. Sync History|7. Choose Theme|$quit"
theme=default
#############
# Functions #
#############
help_text() {
while IFS= read -r line; do
printf "%s\n" "$line"
done <<< "
Usage:
aniwrapper [-dhpqSv] [-t <theme> | -T <config_path>] [<query>]
aniwrapper [-adehpqSv] [-t <theme> | -T <config_path>] [<query>]
aniwrapper -f <directory_path> [-t <theme> | -T <config_path>] [-pSv] [<query>]\
aniwrapper -c [-dhpqSv] [<query>]
aniwrapper -c [-dehpqSv] [<query>]
aniwrapper -Q <query>
aniwrapper -C
Options:
-a enable autoplay
-c enable command-line mode (rofi disabled)
-C connect to history database
-d download episode in command-line mode
-e [<episode> | <begin> - <end>] select episode(s) to stream/download
-f <path_to_directory> (no trailing slash) specify starting directory for play for file mode
-h show this help text
-p enable player selection menu
-P select provider to scrape first
-q enable quality selection
-Q <query> query the history database
-r start script in episode selection using the most recently watched anime
-v verbose output
-S silent mode (suppress output to stdout) [cannot be used with -v]
-t <alter|aniwrapper (default)|dracula|doomone|fancy|material|monokai|nord|nord2|onedark> change rofi theme
@ -60,7 +61,7 @@ Options:
}
lg() {
if ((VERBOSE == 1)); then
if ((IS_VERBOSE)); then
inf "$*"
fi
}
@ -75,7 +76,7 @@ prompt() {
printf "\033[1;34m%s\033[1;35m%s\033[1;34m: \033[0m" "$1" "$2"
}
seppuku() {
die() {
printf "%s\n" "$*"
exit 1
}
@ -86,32 +87,17 @@ quit() {
}
run() {
if ((IS_PLAY_FROM_FILE == 0 && IS_SYNC == 0 && GET_QUALITY == 1)); then
get_quality
fi
if ((SILENT == 1)); then
if ((IS_CUSTOM_THEME == 0)); then
"$CMD" -D"$DPI" -Sq "$QUALITY" -t "$theme" -p "$PLAYER_FN" "$@"
else
"$CMD" -D"$DPI" -Sq "$QUALITY" -T "$CFG_FILE" -p "$PLAYER_FN" "$@"
fi
elif ((VERBOSE == 1)); then
if ((IS_CUSTOM_THEME == 0)); then
"$CMD" -D"$DPI" -vq "$QUALITY" -t "$theme" -p "$PLAYER_FN" "$@"
else
"$CMD" -D"$DPI" -vq "$QUALITY" -T "$CFG_FILE" -p "$PLAYER_FN" "$@"
fi
else
if ((IS_CUSTOM_THEME == 0)); then
"$CMD" -D"$DPI" -q "$QUALITY" -t "$theme" -p "$PLAYER_FN" "$@"
else
"$CMD" -D"$DPI" -q "$QUALITY" -T "$CFG_FILE" -p "$PLAYER_FN" "$@"
fi
if ((IS_CUSTOM_THEME)); then
args+=(-T"$CFG_FILE")
elif ((!IS_CUSTOM_THEME)); then
args+=(-t"$theme")
fi
lg "Running $CMD ${args[*]} -D$DPI $*"
$CMD "${args[@]}" -D"$DPI" "$@"
}
get_quality() {
if ((IS_ROFI == 1)); then
if ((IS_ROFI)); then
selection=$(rofi -dpi "$DPI" -dmenu -config "$CFG_FILE" \
-l 6 -selected-row 0 -a 0 -window-title 'aniwrapper' \
-theme-str 'listview {columns: 1;} window {width: 25%;}' \
@ -119,7 +105,7 @@ get_quality() {
-sep '|' -no-custom <<< "$QUALITIES")
QUALITY=$(awk '{print $2}' <<< "$selection")
else
qualities="best|1080p|720p|480p|360p|worst"
qualities="best|worst"
prompt "Choose quality " "[$qualities]"
read -r QUALITY
while [[ ! "$QUALITY" =~ ($qualities) ]]; do
@ -170,41 +156,51 @@ set_theme() {
}
parse_args() {
while getopts 'vhqcdf:-:t:T:CQ:D:Sp' OPT; do
while getopts 'acCdD:e:f:hpPqQ:rSt:T:v' OPT; do
case "$OPT" in
h)
help_text
exit 0
;;
v)
VERBOSE=1
;;
q)
GET_QUALITY=1
lg "Quality prompt enabled"
a)
IS_AUTOPLAY=1
;;
c)
IS_ROFI=0
lg "Command-line (ani-cli) mode set"
;;
C)
lg "Connecting to history database -> $CFG_DIR/history.sqlite3"
sqlite3 "$CFG_DIR/history.sqlite3"
exit $?
;;
d)
IS_DOWNLOAD=1
lg "Download flag set..."
;;
D)
DPI="$OPTARG"
;;
e)
episodes="$OPTARG"
[[ "$episodes" =~ ^[0-9]+(-[0-9]+)? ]] || die "Invalid episode range: $episodes"
IS_SELECT_EPISODE=0
;;
f)
IS_PLAY_FROM_FILE=1
play_path="$OPTARG"
lg "Play from file flag set... skipping main menu"
lg "PLAY_PATH: $play_path"
;;
t)
theme="$OPTARG"
set_theme "$theme"
h)
help_text
exit 0
;;
C)
lg "Connecting to history database -> $CFG_DIR/history.sqlite3"
sqlite3 "$CFG_DIR/history.sqlite3"
exit $?
p)
IS_ALTERNATE_PLAYER=1
;;
P)
SELECT_PROVIDER=1
;;
q)
GET_QUALITY=1
lg "Quality prompt enabled"
;;
Q)
query="$OPTARG"
@ -212,19 +208,24 @@ parse_args() {
sqlite3 -line "$CFG_DIR/history.sqlite3" "$query"
exit $?
;;
T)
CFG_FILE="$OPTARG"
[ ! -f "$CFG_FILE" ] && seppuku "config file $CFG_FILE does not exist"
IS_CUSTOM_THEME=1
;;
D)
DPI="$OPTARG"
r)
IS_RESUME=1
lg "Selecting previously watched anime"
;;
S)
SILENT=1
;;
p)
IS_ALTERNATE_PLAYER=1
t)
theme="$OPTARG"
set_theme "$theme"
;;
T)
CFG_FILE="$OPTARG"
[ ! -f "$CFG_FILE" ] && die "config file $CFG_FILE does not exist"
IS_CUSTOM_THEME=1
;;
v)
IS_VERBOSE=1
;;
*)
help_text
@ -237,7 +238,7 @@ parse_args() {
get_player() {
msg1="Choose from the supported players, or supply your own player command (full functionality not guaranteed)"
msg2="if using an unsupported player, it must be able to play URLs for streaming from the internet"
if ((IS_ROFI == 1)); then
if ((IS_ROFI)); then
PLAYER_FN=$(
awk '{print $NF}' < <(rofi -dmenu -config "$CFG_FILE" -DPI "$DPI" \
-l 4 -theme-str 'listview {columns: 1;} window {width: 40%;}' \
@ -248,10 +249,6 @@ get_player() {
else
printf "%s\n%s\n" "$msg1" "$msg2"
printf "%s\n" "SUPPORTED PLAYERS:"
# while read -r player; do
# printf "%s\n" "$player"
# done <<< "$(printf "%s\n" "$SUPPORTED_PLAYERS" | sed 's/|/\n/g')"
# bash version
while IFS='|' read -ra players; do
printf "%s\n" "${players[@]}"
done <<< "$SUPPORTED_PLAYERS"
@ -260,36 +257,105 @@ get_player() {
fi
[ -z "$PLAYER_FN" ] && PLAYER_FN=mpv
if ! command -v "$PLAYER_FN" > /dev/null; then
seppuku "ERROR: $PLAYER_FN does not exist"
die "ERROR: $PLAYER_FN does not exist"
fi
}
check_flags() {
# Check if command-line flag is set
if ((VERBOSE == 1 && SILENT == 1)); then
seppuku "verbose and silent options cannot be used together"
# prompts the user to select a provider and returns the provider name and index
get_provider() {
providers="1. Animixplay|2. Xstreamcdn|3. Gogoanime"
if ((IS_ROFI)); then
selection="$(rofi -dmenu -config "$CFG_FILE" -DPI "$DPI" \
-i -l 7 -theme-str 'listview {columns: 1;} window {width: 45%;}' \
-p "Select provider:" -window-title 'aniwrapper' \
-a 0 -sep '|' <<< "$providers")"
[ -z "$selection" ] && selection=1
provider_idx="${selection:0:1}"
else
provider_begin=1
provider_end=3
printf "%s%s\n" "Select provider:" "[$providers]"
prompt "Enter provider [$provider_begin-$provider_end]"
read -r provider_idx
[ -z "$provider_idx" ] && die "ERROR: provider index cannot be empty"
((provider_idx < provider_begin || provider_idx > provider_end)) && die "ERROR: provider index must be between $provider_begin and $provider_end"
fi
if ((IS_DOWNLOAD == 0 && IS_ALTERNATE_PLAYER == 1)); then
while IFS='|' read -ra providers_list; do
for p in "${providers_list[@]}"; do
if [[ "${p:0:1}" == "$provider_idx" ]]; then
lg "provider -> $p | provider index -> $idx" > /dev/stderr
provider="${p:3}"
break
fi
((++idx))
done
done <<< "$providers"
[ -z "$provider" ] && provider="Xstreamcdn"
inf "Selected provider: $provider"
}
# Check passed in flags and set cli arguments
check_flags() {
if ((IS_VERBOSE && SILENT)); then
die "verbose and silent options cannot be used together"
fi
if ((IS_DOWNLOAD && IS_AUTOPLAY)); then
die "autoplay and download options cannot be used together"
fi
if ((IS_DOWNLOAD && IS_PLAY_FROM_FILE)); then
die "download and play from file options cannot be used together"
fi
if ((!IS_DOWNLOAD && IS_ALTERNATE_PLAYER)); then
get_player
lg "SELECTED PLAYER FN -> $PLAYER_FN"
fi
if ((IS_ROFI == 0 && IS_DOWNLOAD == 0)); then
run -c "$@"
exit $?
elif ((IS_ROFI == 0 && IS_DOWNLOAD == 1)); then
args=()
if ((IS_AUTOPLAY)); then
args+=(-a)
fi
if ((!IS_ROFI)); then
args+=(-c)
prompt "Enter download directory"
read -r dl_dir
lg "Download dir: $dl_dir"
if [ ! -d "$dl_dir" ]; then
mkdir -p "$dl_dir" || seppuku "Error creating directory: $dl_dir"
mkdir -p "$dl_dir" || die "Error creating directory: $dl_dir"
fi
run "-cd $dl_dir" "$@"
exit $?
elif ((IS_ROFI == 1 && IS_PLAY_FROM_FILE == 1 && IS_CUSTOM_THEME == 1)); then
run "-f$play_path" -T "$CFG_FILE" "$@"
exit $?
elif ((IS_ROFI == 1 && IS_PLAY_FROM_FILE == 1 && IS_CUSTOM_THEME == 0)); then
run "-f$play_path" -t "$theme" "$@"
args+=(-d"$dl_dir")
fi
if ((IS_DOWNLOAD)); then
args+=(-d "$DEFAULT_DOWNLOAD")
fi
if ((IS_PLAY_FROM_FILE)); then
args+=(-f"$play_path")
fi
if ((IS_ALTERNATE_PLAYER)); then
args+=(-p "$PLAYER_FN")
fi
if ((IS_RESUME)); then
args+=(-r)
fi
if ((SELECT_PROVIDER)); then
get_provider || provider_idx=1
lg "PROVIDER INDEX -> $provider_idx"
args+=(-P"$provider_idx")
fi
if ((SILENT)); then
args+=(-S)
fi
if ((IS_VERBOSE)); then
args+=(-v)
fi
if ((GET_QUALITY)); then
args+=(-q)
fi
if ((!IS_SELECT_EPISODE)); then
args+=(-e"$episodes")
fi
lg "ARGS: ${args[*]}"
if ((IS_AUTOPLAY || IS_DOWNLOAD || !IS_ROFI || IS_RESUME || IS_PLAY_FROM_FILE)); then
run "${args[@]}" "$@"
exit $?
fi
}
@ -304,19 +370,16 @@ get_dl_dir() {
# if dl_dir is none set to current directory
[ "$dl_dir" == "" ] && dl_dir="$DEFAULT_DOWNLOAD"
if [ ! -d "$dl_dir" ]; then
mkdir -p "$dl_dir" || seppuku "Error creating directory: $dl_dir"
mkdir -p "$dl_dir" || die "Error creating directory: $dl_dir"
fi
}
########
# Main #
########
main() {
((SILENT != 1)) && lg "CONFIG DIR: $CFG_DIR"
((SILENT != 1)) && lg "ROFI CFG: $CFG_FILE"
((!SILENT)) && lg "CONFIG DIR: $CFG_DIR"
((!SILENT)) && lg "ROFI CFG: $CFG_FILE"
choice=$(echo "${options[@]}" | rofi -dpi "$DPI" -dmenu -no-custom -sep '|' \
-theme-str 'listview {columns: 1;} window {width: 45%;}' \
-config "$CFG_FILE" -l 7 -i -p "Aniwrapper" -window-title 'aniwrapper')
-theme-str 'listview {columns: 2;} window {width: 45%;}' \
-config "$CFG_FILE" -l 4 -i -p "Aniwrapper" -window-title 'aniwrapper')
[ "$choice" == "$quit" ] && quit
@ -324,37 +387,28 @@ main() {
case "$selection" in
1.)
# ---------------------------------------------------------------------------
# streaming
# ---------------------------------------------------------------------------
lg "Streaming mode"
run
;;
2.)
# ---------------------------------------------------------------------------
# download
# ---------------------------------------------------------------------------
lg "Download anime"
get_dl_dir && run -d "$dl_dir"
;;
3.)
# ---------------------------------------------------------------------------
# continue
# ---------------------------------------------------------------------------
lg "Continue watching"
run -H
;;
4.)
# ---------------------------------------------------------------------------
# play
# ---------------------------------------------------------------------------
lg "Showing recently updated anime"
run -R
;;
5.)
lg "Play from file selected"
IS_PLAY_FROM_FILE=1
span=$(printf '%s\n%s\n' "$(generate_span "Provide a path to a valid directory, or choose from the list below")" "$(generate_span "The program will begin searching for media files from the supplied directory")")
play_dir=$(
rofi -dpi "$DPI" -dmenu -config "$CFG_FILE" \
-l 12 -mesg "$span" -p "Enter path to starting directory:" \
-i -l 12 -mesg "$span" -p "Enter path to starting directory:" \
-async-pre-read 24 -matching 'fuzzy' -window-title 'aniwrapper' \
-sort -sorting-method fzf \
< <(sqlite3 -noheader -list "$CFG_DIR/history.sqlite3" <<< "SELECT directory FROM file_history WHERE filename = 'DIRECTORY' ORDER BY WATCH_DATE DESC;")
@ -363,21 +417,21 @@ main() {
play_dir="${play_dir%% }"
lg "Play dir: $play_dir"
if [ -z "$play_dir" ]; then
mkdir -p "$DEFAULT_DOWNLOAD" || seppuku "error creating default download directory"
mkdir -p "$DEFAULT_DOWNLOAD" || die "error creating default download directory"
run -f"$DEFAULT_DOWNLOAD"
else
run -f"$play_dir"
fi
exit $?
;;
5.)
6.)
lg "Sync history database"
IS_SYNC=1
roficmd="rofi -dpi $DPI -dmenu -config $CFG_FILE -l 0 -p"
username=$($roficmd "Enter the username of the remote user:" -theme-str 'window {width: 45%;}')
[ -z "$username" ] && seppuku "No username provided... exiting"
[ -z "$username" ] && die "No username provided... exiting"
host=$($roficmd "Enter the host for the remote machine (eg 192.168.1.99):" -theme-str 'window {width: 45%;}')
[ -z "$host" ] && seppuku "No host provided... exiting"
[ -z "$host" ] && die "No host provided... exiting"
port=$($roficmd "Enter in the ssh port for remote machine or leave blank for default [22]:" -theme-str 'window {width: 45%;}')
[ -z "$port" ] && port=22
keypath=$($roficmd "Enter path to private key (leave blank if not needed or if unsure):" -theme-str 'window {width: 45%;}')
@ -389,11 +443,8 @@ main() {
quit
fi
;;
6.)
# -----------------------------------------------------------------
# choose theme
# -----------------------------------------------------------------
[ -z "$THEMES" ] && seppuku "No themes provided... exiting"
7.)
[ -z "$THEMES" ] && die "No themes provided... exiting"
theme_idx="$(get_theme_idx)"
lg "Theme index: $theme_idx"
lg "NUM THEMES: $NUM_THEMES"
@ -405,10 +456,7 @@ main() {
set_theme "$theme"
main
;;
7.)
# -----------------------------------------------------------------
# get out
# -----------------------------------------------------------------
8.)
quit
;;
*)
@ -421,9 +469,9 @@ parse_args "$@"
shift $((OPTIND - 1))
if [ $# -gt 0 ]; then
check_flags "$*"
if [ "$IS_DOWNLOAD" -eq 0 ]; then
if ((!IS_DOWNLOAD)); then
run "$*"
elif [ "$IS_DOWNLOAD" -eq 1 ]; then
elif ((IS_DOWNLOAD)); then
get_dl_dir && run -d "$dl_dir" "$*"
fi
else

44
disclaimer.md Normal file
View File

@ -0,0 +1,44 @@
<h1 align="center">Disclaimer</h1>
<div align="center">
<h2>This project: aniwrapper</h2>
<br>
The core aim of this project is to co-relate automation and efficiency to extract what is provided to an user on the internet. Every content available in the project is hosted by external non-affiliated sources.
<br>
<b>Any content served through this project is publicly accessible. If your site is listed in this project, the code is pretty much public. Take necessary measures to counter the exploits used to extract content in your site.</b>
Think of this project as your normal browser, but a bit more straight-forward and specific. While an average browser makes hundreds of requests to get everything from a site, this project goes on to make requests associated with only getting the content served by the sites.
<b>
This project is to be used at the user's own risk, based on their government and laws.
This project has no control on the content it is serving, using copyrighted content from the providers is not going to be accounted for by the developer. It is the user's own risk.
</b>
<br>
<h2>DMCA and Copyright Infrigements</h2>
<br>
<b>
A browser is a tool, and the maliciousness of the tool is directly based on the user.
</b>
This project uses client-side content access mechanisms. Hence, the copyright infrigements or DMCA in this project's regards are to be forwarded to the associated site by the associated notifier of any such claims. As of writing this is gogoplay
<b> Do not harass the maintainer. </b>
<h2>Contacting the maintainer</h2>
<br>
Begin by making a GitHub issue or sending an email to suda@sudacode.com
</div>

View File

@ -28,9 +28,6 @@ The next menu is where you select the anime to watch from a narrowed down list o
</div>
> Half-episodes (ex. saihate-no-paladin episode 7.5) are selectable, however they will not show up in the episodes list.
> To select half episodes add 'h' to the beginning for episodes like '7.5' -> 'h7' to select saihate-no-paladin episode 7.5
Here you will be prompted to select the episode(s) to download
Multiple episodes can be downloaded by giving the episode range like so

View File

@ -1,5 +1,19 @@
.\" Automatically generated by Pandoc 2.14.2
.\" Automatically generated by Pandoc 2.19.2
.\"
.\" Define V font for inline verbatim, using C font in formats
.\" that render this, and otherwise B font.
.ie "\f[CB]x\f[]"x" \{\
. ftr V B
. ftr VI BI
. ftr VB B
. ftr VBI BI
.\}
.el \{\
. ftr V CR
. ftr VI CI
. ftr VB CB
. ftr VBI CBI
.\}
.TH "ANIWRAPPER" "1" "February 4, 2022" "aniwrapper 1.0.0" "Man Page"
.hy
.SH NAME
@ -8,7 +22,7 @@ aniwrapper - A rofi wrapper around ani-cli: a command-line tool to
stream, download, and play anime
.SH SYNOPSIS
.PP
\f[B]aniwrapper\f[R] [-dhpqSv] [-t \f[I]theme\f[R] | -T
\f[B]aniwrapper\f[R] [-adhpqrSv] [-t \f[I]theme\f[R] | -T
\f[I]config_path\f[R]] [\f[I]query\f[R]]
.PD 0
.P
@ -18,7 +32,7 @@ stream, download, and play anime
.PD 0
.P
.PD
\f[B]aniwrapper\f[R] -c [-dhpqSv] [\f[I]query\f[R]]
\f[B]aniwrapper\f[R] -c [-dhpqrSv] [\f[I]query\f[R]]
.PD 0
.P
.PD
@ -43,6 +57,9 @@ aniwrapper.rasi theme
.IP \[bu] 2
best quality
.TP
\f[B]-a\f[R]
Enable autoplay in streaming mode
.TP
\f[B]-c\f[R]
Enable command-line mode (disable \f[B]rofi\f[R])
.TP
@ -53,6 +70,9 @@ Connect to the history database
\f[B]-d\f[R]
Enable downloading anime in command-line mode
.TP
\f[B]-e\f[R] \f[I]episode\f[R] \f[B]or\f[R] \f[I]begin_episode - end_episode\f[R]
Select episode(s) to stream/download
.TP
\f[B]-f\f[R]
Specify the starting search directory for \[lq]Play from File\[rq] mode
.TP
@ -62,9 +82,15 @@ Display the help message
\f[B]-p\f[R]
Enable video player selection menu
.TP
\f[B]-P\f[R]
Enable provider selection menu
.TP
\f[B]-q\f[R]
Enable quality selection
.TP
\f[B]-r\f[R]
Start script at episode selection for the most recently watched anime
.TP
\f[B]-Q\f[R] \f[I]query\f[R]
Run a query on the history databse
.TP

View File

@ -12,9 +12,9 @@ aniwrapper - A rofi wrapper around ani-cli: a command-line tool to stream, downl
# SYNOPSIS
**aniwrapper** [-dhpqSv] [-t _theme_ | -T _config_path_] [_query_]\
**aniwrapper** [-adhpqrSv] [-t _theme_ | -T _config_path_] [_query_]\
**aniwrapper** -f _directory_path_ [-t _theme_ | -T _config_path_] [-pSv] [_query_]\
**aniwrapper** -c [-dhpqSv] [_query_]\
**aniwrapper** -c [-dhpqrSv] [_query_]\
**aniwrapper** -Q _query_\
**aniwrapper** -C
@ -32,6 +32,9 @@ Defaults:
- aniwrapper.rasi theme
- best quality
**-a**
: Enable autoplay in streaming mode
**-c**
: Enable command-line mode (disable **rofi**)
@ -41,6 +44,9 @@ Defaults:
**-d**
: Enable downloading anime in command-line mode
**-e** _episode_ **or** _begin_episode - end_episode_
: Select episode(s) to stream/download
**-f**
: Specify the starting search directory for "Play from File" mode
@ -50,9 +56,15 @@ Defaults:
**-p**
: Enable video player selection menu
**-P**
: Enable provider selection menu
**-q**
: Enable quality selection
**-r**
: Start script at episode selection for the most recently watched anime
**-Q** _query_
: Run a query on the history databse

171
lib/ani-cli/UI Normal file
View File

@ -0,0 +1,171 @@
#!/usr/bin/env bash
VERSION="1.0.0"
retry() {
err "$*"
prompt
}
# display error message and exit
die() {
((!SILENT)) && printf "\033[1;31m%s\033[0m\n" "$*" >&2
exit 1
}
# display an error message to stderr (in red)
err() {
((!SILENT)) && printf "\33[2K\r\033[1;31m%s\033[0m\n" "$*" >&2
}
# display a log message if verbose mode is enabled
lg() {
((VERBOSE)) && printf "\033[1;35m%s\033[0m\n" "$*" >&2
}
# display an informational message (first argument in green, second in magenta)
inf() {
printf "\33[2K\r\033[1;35m%s \033[1;35m%s\033[0m\n" "$1" "$2"
}
progress() {
((!SILENT)) && printf "\33[2K\r\033[1;34m%s\033[0m\n" "$1" >&2
}
# prompts the user with message in $1-2 ($1 in blue, $2 in magenta) and saves the input to the variables in $REPLY and $REPLY2
prompt() {
printf "\033[1;35m%s\033[1;35m%s\033[1;34m\033[0m: " "$1" "$2"
}
# displays an even (cyan) line of a menu line with $2 as an indicator in [] and $1 as the option
menu_line_even() {
printf "\033[1;36m(\033[1;36m%s\033[1;36m) \033[1;36m%s\033[0m\n" "$2" "$1"
}
# displays an odd (yellow) line of a menu line with $2 as an indicator in [] and $1 as the option
menu_line_odd() {
printf "\033[1;33m(\033[1;33m%s\033[1;33m) \033[1;33m%s\033[0m\n" "$2" "$1"
}
# display alternating menu lines (even and odd)
menu_line_alternate() {
menu_line_parity=${menu_line_parity:-0}
if [ "$menu_line_parity" -eq 0 ]; then
menu_line_odd "$1" "$2"
menu_line_parity=1
else
menu_line_even "$1" "$2"
menu_line_parity=0
fi
}
# displays a warning (red) line of a menu line with $2 as an indicator in [] and $1 as the option
menu_line_strong() {
printf "\033[1;34m[\033[1;33m%s\033[1;34m] \033[1;33m%s\033[0m\n" "$2" "$1"
}
# Select anime from query results
anime_selection() {
search_results=$*
count=1
while read -r anime_id; do
anime_id=$(printf "%s" "$anime_id" | sed -E 's/\-episode\-.*//')
menu_line_alternate "$anime_id" "$count"
: count=$((count += 1))
done <<< "$search_results"
prompt "Enter choice"
read -r choice
# Check if input is a number
[[ "$choice" -eq "$choice" ]] 2> /dev/null || die "Invalid number entered"
count=1
while read -r anime_id; do
if [[ "$count" -eq "$choice" ]]; then
anime_id=$(printf "%s" "$anime_id" | sed -E 's/\-episode\-.*//')
selection_id=$anime_id
break
fi
count=$((count + 1))
done <<< "$search_results"
[[ -z "$selection_id" ]] && die "Invalid number entered"
insert_history "search" "$selection_id" &
lg "Selection: $selection_id"
progress "(Gogoanime) Searching Episodes.."
episode_list "$selection_id"
return 0
}
# select episode from query results
episode_selection() {
ep_choice_start=1
if [ -n "$LAST_EP_NUMBER" ]; then
[[ "$is_download" -eq 1 ]] &&
inf "Range of episodes can be specified:" "start_number end_number"
inf "Anime:" "$anime_id"
prompt "Choose episode " "[$FIRST_EP_NUMBER-$LAST_EP_NUMBER]"
read -r ep_choice_start ep_choice_end
[[ -z "$ep_choice_end" ]] && ep_choice_end="$ep_choice_start"
fi
if (((ep_choice_start < 0 || ep_choice_start > LAST_EP_NUMBER) || ep_choice_end < ep_choice_start || ep_choice_end > LAST_EP_NUMBER)); then
die "Invalid episode/range entered: ep_start -> $ep_choice_start | ep_end -> $ep_choice_end"
fi
}
continue_watching() {
inf "Continue watching $selection_id?"
prompt "Next episode -> $((episode + 1)) [Y/n]"
read -r choice
[ -z "$choice" ] && choice="y"
[[ "$choice" =~ ^(y|Y|Yes)$ ]] && return 0 || return 1
}
# get the search query from user or from args
get_search_query() {
if [ $# -gt 0 ]; then
query="${*// /-}"
else
prompt "Search Anime"
read -r query
query="${query// /-}"
fi
}
get_dl_dir() {
prompt "Enter download directory"
read -r download_dir
lg "Download dir: $download_dir"
[ -z "$download_dir" ] && download_dir="$HOME/Videos/sauce/"
if [ ! -d "$download_dir" ]; then
mkdir -p "$download_dir" || die "Error creating directory: $download_dir"
fi
}
# sets the video quality
set_video_quality() {
qualities="best|worst"
prompt "Choose quality [$qualities]"
read -r quality
while [[ ! "$quality" =~ ($qualities) ]]; do
lg "$quality not a valid quality"
prompt "Choose quality [$qualities]"
read -r quality
done
[ -z "$quality" ] && die "No quality selected"
NEW_QUALITY=1
}
# gets the video quality from the user
get_quality() {
qualities="best|worst"
prompt "Choose quality " "[$qualities]"
read -r quality
while [[ ! "$quality" =~ ($qualities) ]]; do
lg "$quality not a valid quality -> [$qualities]"
prompt "Choose quality " "[$qualities]"
read -r quality
done
lg "selected quality: $quality"
}
# vim :ft=sh

212
lib/ani-cli/UI-ROFI Normal file
View File

@ -0,0 +1,212 @@
#!/usr/bin/env bash
VERSION="1.0.0"
retry() {
err "$*"
prompt
}
# display error message and exit
die() {
((!SILENT)) && printf "\033[1;31m%s\033[0m\n" "$*" >&2
exit 1
}
# display an error message to stderr (in red)
err() {
((!SILENT)) && printf "\33[2K\r\033[1;31m%s\033[0m\n" "$*" >&2
}
# display a log message if verbose mode is enabled
lg() {
((VERBOSE)) && printf "\033[1;35m%s\033[0m\n" "$*" >&2
}
# display an informational message (first argument in green, second in magenta)
inf() {
printf "\33[2K\r\033[1;35m%s \033[1;35m%s\033[0m\n" "$1" "$2"
}
progress() {
((!SILENT)) && printf "\33[2K\r\033[1;34m%s\033[0m\n" "$1" >&2
}
# prompts the user with message in $1-2 ($1 in blue, $2 in magenta) and saves the input to the variables in $REPLY and $REPLY2
prompt() {
printf "\033[1;35m%s\033[1;35m%s\033[1;34m\033[0m: " "$1" "$2"
}
# displays an even (cyan) line of a menu line with $2 as an indicator in [] and $1 as the option
menu_line_even() {
printf "\033[1;36m(\033[1;36m%s\033[1;36m) \033[1;36m%s\033[0m\n" "$2" "$1"
}
# displays an odd (yellow) line of a menu line with $2 as an indicator in [] and $1 as the option
menu_line_odd() {
printf "\033[1;33m(\033[1;33m%s\033[1;33m) \033[1;33m%s\033[0m\n" "$2" "$1"
}
# display alternating menu lines (even and odd)
menu_line_alternate() {
menu_line_parity=${menu_line_parity:-0}
if [ "$menu_line_parity" -eq 0 ]; then
menu_line_odd "$1" "$2"
menu_line_parity=1
else
menu_line_even "$1" "$2"
menu_line_parity=0
fi
}
# displays a warning (red) line of a menu line with $2 as an indicator in [] and $1 as the option
menu_line_strong() {
printf "\033[1;34m[\033[1;33m%s\033[1;34m] \033[1;33m%s\033[0m\n" "$2" "$1"
}
# Select anime from query results
anime_selection() {
search_results=$*
menu=""
searched=""
cnt=0
while read -r anime_id; do
anime_id=$(printf "%s" "$anime_id" | sed -E 's/\-episode\-.*//')
[[ -z "$menu" ]] && menu="$((cnt + 1)). $anime_id" ||
menu="$menu|$((cnt + 1)). $anime_id"
if ! check_db "search" "$anime_id"; then
[[ -z "$searched" ]] && searched="$cnt" || searched="$searched, $cnt"
fi
((++cnt))
done <<< "$search_results"
menu="$menu|$((++cnt)). Search another anime|$((++cnt)). Quit"
# get the anime from indexed list
msg="$(generate_span "Query: $query")"
selection="$(rofi -dpi "$DPI" -dmenu -no-custom \
-async-pre-read 33 -config "$ROFI_CFG" -l 15 -i -sep '|' \
-mesg "$msg" -a "$searched" -p "Enter selection" -window-title 'aniwrapper' <<< "$menu")"
choice="${selection%%.*}" # remmove everything from . to end
lg "CHOICE: $choice"
if ((choice == cnt)); then
die "Quitting"
elif ((choice == --cnt)); then
stream
return $?
fi
# Check if input is a number
[[ "$choice" -eq "$choice" ]] 2> /dev/null || die "Invalid number entered"
count=1
while read -r anime_id; do
if [[ "$count" -eq "$choice" ]]; then
anime_id=$(printf "%s" "$anime_id" | sed -E 's/\-episode\-.*//')
selection_id=$anime_id
break
fi
count=$((count + 1))
done <<< "$search_results"
[[ -z "$selection_id" ]] && die "Invalid number entered"
insert_history "search" "$selection_id" &
lg "Selection: $selection_id"
progress "(Gogoanime) Searching Episodes.."
episode_list "$selection_id"
return 0
}
# select episode from query results
episode_selection() {
ep_choice_start=1
lg "Anime ID: $anime_id"
stmt="SELECT episode_number FROM watch_history WHERE anime_name = '$anime_id';"
# Get Watch History for $anime_id as comma separated list
watch_history=""
while read -r i; do
if ((FIRST_EP_NUMBER == 0)); then
[[ -z "$watch_history" ]] && watch_history="$((i))" || watch_history="$watch_history, $((i))"
else
[[ -z "$watch_history" ]] && watch_history="$((--i))" || watch_history="$watch_history, $((--i))"
fi
done < <(run_stmt "$stmt")
lg "Episode watch history -> $watch_history"
# get user choice and set the start and end
msg1="Anime Name: $anime_id"
msg2="Range of episodes can be provided as: START_EPISODE - END_EPISODE"
[[ "$is_download" -eq 1 ]] && msg=$(printf "%s\n%s" "$(generate_span "$msg1")" "$(generate_span "$msg2")") || msg=$(printf "%s\n" "$(generate_span "$msg1")")
choice=$(
seq "$FIRST_EP_NUMBER" "$LAST_EP_NUMBER" |
rofi -dpi "$DPI" -dmenu -l 12 \
-theme-str 'window {width: 45%;}' \
-a "$watch_history" \
-p "Select Episode [$FIRST_EP_NUMBER, $LAST_EP_NUMBER]:" \
-mesg "$msg" -window-title 'aniwrapper' \
-config "$ROFI_CFG"
)
ep_choice_start=$(printf '%s\n' "${choice}" | awk '{print $1}')
ep_choice_end=$(printf '%s\n' "${choice}" | awk '{print $NF}')
lg "START: $ep_choice_start | END: $ep_choice_end"
if (((ep_choice_start < 0 || ep_choice_start > LAST_EP_NUMBER) || ep_choice_end < ep_choice_start || ep_choice_end > LAST_EP_NUMBER)); then
die "Invalid episode/range entered: ep_start -> $ep_choice_start | ep_end -> $ep_choice_end"
fi
}
continue_watching() {
msg="$(printf '%s\n%s' "$(generate_span "Anime: $anime_id")" "$(generate_span "Next episode: $((episode + 1))")")"
choice=$(rofi -dmenu -dpi "$DPI" -config "$ROFI_CFG" \
-theme-str 'listview {columns: 1;} window {width: 25%;}' \
-i -l 2 -no-custom -sep '|' -a 0 -mesg "$msg" \
-p "Continue watching?" -window-title 'aniwrapper' <<< "Yes|No")
[[ "$choice" =~ ^(y|Y|Yes)$ ]] && return 0 || return 1
}
# get the search query from user or from args
get_search_query() {
if [ $# -gt 0 ]; then
query="${*// /-}"
else
stmt="SELECT id || '. ' || anime_name FROM search_history ORDER BY search_date DESC;"
msg="Choose from list of searched anime below, or enter a unique name of an anime to search for"
query=$(rofi -dpi "$DPI" -dmenu -l 15 -p "Search Anime:" \
-mesg "$(generate_span "$msg")" \
-config "$ROFI_CFG" -window-title 'aniwrapper' < <(run_stmt "$stmt"))
query="${query#*\. }" # remove [1-9]. from beginning of query
query="${query// /-}" # replace spaces with -
fi
}
get_dl_dir() {
download_dir=$(
rofi -dpi "$DPI" -dmenu -config "$ROFI_CFG" \
-theme-str 'listview {columns: 1;} window {width: 45%;}' \
-mesg "$(generate_span "Enter the path to the download directory, or leave blank to go with the default: $HOME/Videos/sauce/")" \
-l 1 -p "Enter download dir:" -window-title 'aniwrapper'
)
[ -z "$download_dir" ] && download_dir="$HOME/Videos/sauce/"
if [ ! -d "$download_dir" ]; then
mkdir -p "$download_dir" || die "Error creating directory: $download_dir"
fi
}
# sets the video quality
set_video_quality() {
qualities="1. best|2. worst"
while IFS='|' read -ra quals; do
for q in "${quals[@]}"; do
if [[ "$(awk '{ print $NF }' <<< "$q")" == "$quality" ]]; then
cur_quality="$((${q:0:1} - 1))"
break
fi
done
done <<< "$qualities"
choice=$(rofi -dmenu -dpi "$DPI" -config "$ROFI_CFG" \
-theme-str 'listview {columns: 1;} window {width: 25%;}' \
-i -l 6 -no-custom -sep '|' -a "$cur_quality" -mesg "$(generate_span "Current quality: $quality")" \
-p "Choose quality:" -window-title 'aniwrapper' -selected-row "$cur_quality" <<< "$qualities")
quality=$(awk '{ print $2 }' <<< "$choice")
NEW_QUALITY=1
}
# vim :ft=sh

121
lib/ani-cli/UI-play Normal file
View File

@ -0,0 +1,121 @@
# display a log message if verbose mode is enabled
lg() {
((VERBOSE)) && printf "\033[1;35m%s\033[0m\n" "$*" >&2
}
# display error message and exit
die() {
((!SILENT)) && printf "\033[1;31m%s\033[0m\n" "$*" >&2
exit 1
}
# gets the list of directories and playable files from the passed in directory
# sets the $watched list to the list of watched files
get_directory_data() {
search_dir="$1"
inputlist=""
watched=""
cnt=1
[ "$search_dir" = "/" ] && cnt=0 # account for no ../ on /
for directory in "$1"/*; do
directory="${directory##*/}"
[ ! -d "$search_dir/$directory" ] && continue
[ -z "$inputlist" ] && inputlist="$directory" || inputlist="$inputlist|$directory"
if ! check_db "directory" "$search_dir/$directory"; then
lg "$search_dir/$directory opened before... adding $cnt to list" 1> /dev/stderr
[ -z "$watched" ] && watched="$cnt" || watched="$watched, $cnt"
fi
((++cnt))
done
shopt -s nullglob # set nullglob to avoid printing output if no files with extension exist
shopt -s nocaseglob # case insensitive globbing
for filename in "$search_dir"/*.{mp4,mkv,ts,mp3,webm}; do
filename="${filename##*/}"
[ -z "$inputlist" ] && inputlist="$filename" || inputlist="$inputlist|$filename"
if ! check_db "file" "$search_dir" "$filename"; then
lg "$filename watched before... adding $cnt to list" 1> /dev/stderr
[ -z "$watched" ] && watched="$cnt" || watched="$watched, $cnt"
fi
((++cnt))
done
shopt -u nullglob
shopt -u nocaseglob
if [[ -n "$inputlist" && "$search_dir" != / ]]; then
inputlist="../|$inputlist|Back|Quit"
elif [[ -z "$inputlist" && "$search_dir" != / ]]; then
inputlist="../|Back|Quit"
elif [[ "$search_dir" = / ]]; then
inputlist="$inputlist|Quit"
else
inputlist="Quit"
fi
lg "INPUT LIST: $inputlist" 1> /dev/stderr
lg "WATCHED LIST: $watched" 1> /dev/stderr
}
# recursive function for finding path to video file given a starting directory
find_media() {
inp="$1"
[ -z "$inp" ] && die "No directory"
lg "BEGIN find_media() on $inp" 1> /dev/stderr
# base case hit when a file is found
if [ -f "$inp" ]; then
printf "%s\n" "$inp"
return 0
fi
get_directory_data "$inp"
selection="$(rofi -dpi "$DPI" -dmenu -no-custom -async-pre-read 33 -config "$ROFI_CFG" \
-l 15 -i -sep '|' -mesg "$(generate_span "Current directory: $inp")" -a "$watched" \
-p "Enter selection" -window-title 'aniwrapper' <<< "$inputlist")"
[ -z "$selection" ] && return 1
case "$selection" in
Back | ../)
dotdotslash="${inp%/*}"
[ -z "$dotdotslash" ] && dotdotslash="/"
insert_history "directory" "$dotdotslash"
find_media "$dotdotslash"
;;
Quit)
return 1
;;
*)
if [ -d "$inp/$selection" ]; then
insert_history "directory" "$inp/$selection"
if [ "$inp" = "/" ]; then
find_media "/$selection"
else
find_media "$inp/$selection"
fi
else
find_media "$inp/$selection"
fi
;;
esac
}
# opens the passed in file with $PLAYER_FN
play_file() {
lg "Checking if file is playable"
if [[ "$1" =~ (\.mp4|\.mkv|\.ts|\.webm)$ ]]; then
filename="${1##*/}"
directory="${1%/*}"
insert_history "file" "$directory" "$filename"
notification "Playing $1"
case "$PLAYER_FN" in
mpv)
nohup "$PLAYER_FN" --force-media-title="aniwrapper: play-from-file - $1" "$1" > /dev/null 2>&1 &
;;
*)
nohup "$PLAYER_FN" "$1" > /dev/null 2>&1 &
;;
esac
return $?
else
die "File: $1 is not playable... Quitting"
fi
}
# vim: ft=sh

151
lib/ani-cli/db Normal file
View File

@ -0,0 +1,151 @@
# runs sql command on the history database
run_stmt() {
printf "%s\n" "$1" | sqlite3 -noheader -list "$HISTORY_DB"
}
# Return number of matches for anime/episode in db
check_db() {
case "$1" in
directory)
stmt="SELECT COUNT(*) FROM file_history WHERE directory = '$2';"
;;
file)
stmt="SELECT COUNT(*) FROM file_history WHERE directory = '$2' AND filename = '$3';"
;;
search)
stmt="SELECT COUNT(*) FROM search_history WHERE anime_name = '$2';"
;;
watch | sync)
stmt="SELECT COUNT(*) FROM watch_history WHERE anime_name = '$2' AND episode_number = '$3';"
;;
anime)
stmt="SELECT COUNT(*) FROM anime WHERE anime_name = '$2';"
;;
esac
res=$(run_stmt "$stmt")
return "$res"
}
# return true (0) if $source_dt > $target_dt
check_date() {
source_dt="$1"
target_dt="$2"
if [[ "$source_dt" < "$target_dt" ]] || [[ "$source_dt" == "$target_dt" ]]; then
return 1
else
return 0
fi
}
# updates search/watch date for passed in anime
update_date() {
datetime=$(date +'%Y-%m-%d %H:%M:%S')
stmt=""
case "$1" in
directory)
stmt="UPDATE file_history SET watch_date = '$datetime' WHERE directory = '$2' and filename = 'DIRECTORY';"
;;
file)
stmt="UPDATE file_history SET watch_date = '$datetime' WHERE directory = '$2' and filename = '$3';"
;;
search)
stmt="UPDATE search_history SET search_date = '$datetime' WHERE anime_name = '$2';"
;;
sync)
temp_dt="${3// /:}"
[ -z "$temp_dt" ] && return 1
hist_dt=$(run_stmt "SELECT watch_date FROM watch_history WHERE anime_name='$2' AND episode_number='$3';")
hist_dt="${hist_dt// /:}"
if ! check_date "$hist_dt" "$temp_dt"; then
lg "Passed in date is older or same than current date... doing nothing"
return 1
fi
stmt="UPDATE watch_history SET watch_date = '$temp_dt' WHERE anime_name = '$2' AND episode_number = $3;"
;;
watch)
stmt="UPDATE watch_history SET watch_date = '$datetime' WHERE anime_name = '$2' AND episode_number = $3;"
;;
anime)
return
;;
esac
lg "UPDATE STMT -> $stmt"
run_stmt "$stmt"
}
# inserts into search/watch history db
# check the anime_name/id
insert_history() {
datetime=$(date +'%Y-%m-%d %H:%M:%S')
lg "Checking if ($*) exists in db"
if ! check_db "$@"; then
lg "Match found... Updating row in history db..."
update_date "$@"
res=$?
else
lg "Row not found in DB... inserting"
case "$1" in
directory)
stmt="INSERT INTO file_history(directory, filename, watch_date) VALUES('$2', 'DIRECTORY', '$datetime');"
;;
file)
stmt="INSERT INTO file_history(directory, filename, watch_date) VALUES('$2', '$3', '$datetime');"
;;
search)
stmt="INSERT INTO search_history(anime_name, search_date) VALUES('$2', '$datetime');"
;;
watch)
stmt="INSERT INTO watch_history(anime_name, episode_number, watch_date) VALUES('$2', '$3', '$datetime');"
;;
sync)
stmt="INSERT INTO watch_history(anime_name, episode_number, watch_date) VALUES('$2', '$3', '$4');"
;;
anime)
stmt="INSERT INTO anime(anime_name, start_episode, end_episode, data_date) VALUES('$2', $3, $4, '$datetime');"
;;
esac
lg "INSERT STATEMENT -> $stmt"
run_stmt "$stmt"
res=$?
fi
return $res
}
sync_search_history() {
cnt=0
errs=0
while read -r line; do
anime_name=$(awk -F '|' '{print $2}' <<< "$line")
if sqlite3 -noheader "$HISTORY_DB" "SELECT COUNT(*) FROM search_history WHERE anime_name = '$anime_name'"; then
search_date=$(awk -F '|' '{print $3}' <<< "$line")
if ! sqlite3 "$HISTORY_DB" "INSERT INTO search_history(anime_name, search_date) VALUES('$anime_name', '$search_date')"; then
((++errs))
continue
fi
((++cnt))
fi
done < <(sqlite3 -list -noheader "$temp_db" "SELECT * FROM search_history")
lg "$cnt rows inserted into search_history table"
lg "$errs errors on insert"
}
sync_watch_history() {
cnt=0
errs=0
while read -r line; do
anime_name="${line/ //}"
while read -r ep; do
episode_num=$(awk -F '|' '{print $1}' <<< "$ep")
watch_date=$(awk -F '|' '{print $NF}' <<< "$ep")
if ! insert_history "sync" "$anime_name" "$episode_num" "$watch_date"; then
((++errs))
continue
fi
((++cnt))
done < <(sqlite3 -list -noheader "$temp_db" "SELECT episode_number, watch_date FROM watch_history WHERE anime_name = '$anime_name'")
done < <(sqlite3 -list -noheader "$temp_db" "SELECT anime_name FROM watch_history")
lg "$cnt rows inserted into watch_history table"
lg "$errs rows skipped on insert"
}
# vim: ft=sh

View File

@ -7,7 +7,7 @@
######################
VERBOSE=0
log() {
lg() {
if [[ "$VERBOSE" -eq 1 ]]; then
printf "%s\n" "$*"
fi
@ -16,7 +16,7 @@ log() {
if [[ $# -ge 1 ]]; then
if [[ "$1" == "-v" || "$1" == "--verbose" ]]; then
VERBOSE=1
log "VERBOSE LOGGING ENABLED"
lg "VERBOSE lgGING ENABLED"
fi
fi
@ -25,8 +25,8 @@ DB="history.sqlite3"
DIR="${XDG_CONFIG_HOME:-$HOME/.config}/aniwrapper"
MPV_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/mpv"
log "CONFIG DIR:" "$DIR"
log "MPV DIR:" "$MPV_DIR"
lg "CONFIG DIR:" "$DIR"
lg "MPV DIR:" "$MPV_DIR"
# executes aniwrapper setup
# 1. create the aniwrapper directory in $XDG_CONFIG_HOME
@ -35,43 +35,48 @@ log "MPV DIR:" "$MPV_DIR"
# 4. move skip-intro.lua into mpv/scripts folder
# 5. move the aniwrapper icon to $XDG_CONFIG_HOME/aniwrapper/ directory
run_setup() {
log "INSTALL DIR: $DIR"
lg "INSTALL DIR: $DIR"
if [[ ! -d "$DIR" ]]; then
log "Creating directory $DIR"
lg "Creating directory $DIR"
mkdir -p "$DIR"
log "Directory created"
lg "Directory created"
fi
log "CREATING HISTORY DATABASE IF NOT EXISTS"
lg "CREATING HISTORY DATABASE IF NOT EXISTS"
sqlite3 "$DIR/$DB" < sql/history.sql
log "FINISHED CREATING DB"
lg "FINISHED CREATING DB"
# log "themes directory does not exist in filesystem... Creating and moving themes"
lg "INSTALLING UI FILES TO $DIR/lib/ani-cli"
mkdir -p "$DIR/lib/ani-cli"
cp -r lib/ani-cli/* "$DIR/lib/ani-cli/"
lg "FINISHED INSTALLING UI FILES"
# lg "themes directory does not exist in filesystem... Creating and moving themes"
mkdir -p "$DIR/themes"
cp themes/* "$DIR/themes/"
log "Theme files moved..."
lg "Theme files moved..."
log "Creating mpv/scripts/ directory if it doesn't exist..."
lg "Creating mpv/scripts/ directory if it doesn't exist..."
mkdir -p "$MPV_DIR/scripts/"
if [[ ! -f "$MPV_DIR/scripts/skip-intro.lua" ]]; then
log "Moving skip-intro.lua into mpv scripts directory..."
lg "Moving skip-intro.lua into mpv scripts directory..."
cp lua/skip-intro.lua "$MPV_DIR/scripts/"
log "Moved skip-intro.lua into scripts directory..."
lg "Moved skip-intro.lua into scripts directory..."
else
log "skip-intro.lua already exists in $XDG_CONFIG_HOME/mpv/scripts/... skipping"
lg "skip-intro.lua already exists in $XDG_CONFIG_HOME/mpv/scripts/... skipping"
fi
if [[ ! -d "$DIR/icons" ]]; then
log "Creating icons directory"
lg "Creating icons directory"
mkdir -p "$DIR/icons"
fi
cp .assets/icons/* "$DIR/icons/"
log "Installed icons in config directory..."
lg "Installed icons in config directory..."
}
if run_setup; then
log "Setup Complete...."
lg "Setup Complete...."
else
printf "%s\n" "There was an error during setup"
exit 1

View File

@ -24,8 +24,7 @@ CREATE TABLE IF NOT EXISTS watch_history (
episode_number integer NOT NULL,
watch_date DATETIME NOT NULL,
CHECK (LENGTH(anime_name) > 0),
CHECK (episode_number > 0),
UNIQUE (anime_name, episode_number, watch_date)
UNIQUE (anime_name, episode_number)
);
CREATE TABLE IF NOT EXISTS search_history (
@ -35,6 +34,6 @@ CREATE TABLE IF NOT EXISTS search_history (
CHECK (LENGTH(anime_name) > 0)
);
CREATE UNIQUE INDEX IF NOT EXISTS anime_search_idx ON search_history (anime_name, search_date);
CREATE UNIQUE INDEX IF NOT EXISTS anime_search_idx ON search_history (anime_name);
CREATE UNIQUE INDEX IF NOT EXISTS watch_anime_episode_idx ON watch_history (anime_name, episode_number);
CREATE UNIQUE INDEX IF NOT EXISTS dir_filename_idx ON file_history (directory, filename);