mirror of
https://github.com/mrfluffy-dev/kami.git
synced 2026-01-17 12:50:32 +00:00
added anilist tracking
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
use crate::main;
|
||||
use crate::open_video;
|
||||
use crate::{anime_ep_range, anime_link, anime_names};
|
||||
use crate::{get_anime_id, get_token, get_user_anime_progress, update_anime_progress};
|
||||
use crate::{int_input, string_input};
|
||||
use colored::Colorize;
|
||||
//use crate
|
||||
pub fn anime_stream(search: String, episode: u32) {
|
||||
let token = get_token();
|
||||
let query = if search != "" {
|
||||
search
|
||||
} else {
|
||||
@@ -40,9 +42,11 @@ pub fn anime_stream(search: String, episode: u32) {
|
||||
let title = &anime_list[anime_num];
|
||||
let ep_range = anime_ep_range(title);
|
||||
// if there is only one episode, then don't ask user to choose episode
|
||||
let id = get_anime_id(&title.replace("-", " "));
|
||||
if ep_range == 1 {
|
||||
let link = anime_link(title, 1);
|
||||
open_video(link);
|
||||
update_anime_progress(id, &title.replace("-", " "), 1, &token);
|
||||
main();
|
||||
} else {
|
||||
let mut ep_num: usize = usize::MAX;
|
||||
@@ -52,6 +56,8 @@ pub fn anime_stream(search: String, episode: u32) {
|
||||
} else if episode != 0 {
|
||||
ep_num = episode as usize;
|
||||
} else {
|
||||
let current_progress = get_user_anime_progress(id, &token);
|
||||
println!("you are currently on episode: {}", current_progress);
|
||||
println!("select episode 1-{}: ", ep_range);
|
||||
while ep_num == usize::max_value() || ep_num > ep_range as usize {
|
||||
ep_num = int_input("Enter episode number: ");
|
||||
@@ -63,6 +69,9 @@ pub fn anime_stream(search: String, episode: u32) {
|
||||
loop {
|
||||
let link = anime_link(title, ep_num as u64);
|
||||
open_video(link);
|
||||
let id = get_anime_id(&title.replace("-", " "));
|
||||
println!("{}", get_user_anime_progress(id, &token));
|
||||
update_anime_progress(id, &title.replace("-", " "), ep_num, &token);
|
||||
println!("{}", "n: next episode".green());
|
||||
println!("{}", "p: previous episode".yellow());
|
||||
println!("{}", "s: search another anime".green());
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod anime;
|
||||
pub mod player;
|
||||
pub mod scraper;
|
||||
pub mod anime;
|
||||
pub mod trackers;
|
||||
|
||||
183
src/anime/trackers.rs
Normal file
183
src/anime/trackers.rs
Normal file
@@ -0,0 +1,183 @@
|
||||
use crate::string_input;
|
||||
use isahc::{ReadResponseExt, Request, RequestExt};
|
||||
use serde_json::json;
|
||||
use std::fs;
|
||||
|
||||
pub fn get_token() -> String {
|
||||
//if not on windows create folder ~/.config/kami
|
||||
let config_path = dirs::config_dir().unwrap().join("kami");
|
||||
if !config_path.exists() {
|
||||
fs::create_dir_all(&config_path).unwrap();
|
||||
}
|
||||
let token_path = config_path.join("token.txt");
|
||||
if !token_path.exists() {
|
||||
//create empty file
|
||||
fs::File::create(&token_path).unwrap();
|
||||
} else {
|
||||
//read token from file
|
||||
let token = fs::read_to_string(&token_path).unwrap();
|
||||
if token.is_empty() {
|
||||
println!("please go to the below link and copy and past the token below");
|
||||
println!(
|
||||
"https://anilist.co/api/v2/oauth/authorize?client_id=9121&response_type=token"
|
||||
);
|
||||
let token = string_input("token: ");
|
||||
fs::write(&token_path, token).unwrap();
|
||||
}
|
||||
}
|
||||
let token = fs::read_to_string(&token_path).unwrap();
|
||||
token
|
||||
}
|
||||
|
||||
pub fn get_anime_id(anime: &str) -> i32 {
|
||||
const QUERY: &str = "
|
||||
query ($id: Int, $search: String) {
|
||||
Media (id: $id, search: $search, type: ANIME) {
|
||||
id
|
||||
title {
|
||||
native
|
||||
romaji
|
||||
english
|
||||
}
|
||||
}
|
||||
}
|
||||
";
|
||||
let json = json!({
|
||||
"query": QUERY,
|
||||
"variables": {
|
||||
"search": anime,
|
||||
}
|
||||
});
|
||||
let resp = Request::builder()
|
||||
.method("POST")
|
||||
.uri("https://graphql.anilist.co/")
|
||||
.header("Content-Type", "application/json")
|
||||
.header("Accept", "application/json")
|
||||
.body(json.to_string())
|
||||
.unwrap()
|
||||
.send()
|
||||
.unwrap()
|
||||
.text();
|
||||
//println!("{}", resp);
|
||||
let regex = regex::Regex::new(r#"id":(.*?),"#).unwrap();
|
||||
let resp: String = resp.as_ref().unwrap().to_string();
|
||||
let id = regex
|
||||
.captures(&resp)
|
||||
.unwrap()
|
||||
.get(1)
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.parse::<i32>()
|
||||
.unwrap();
|
||||
id
|
||||
}
|
||||
|
||||
//get the user id from the token
|
||||
fn get_user_id(token: &str) -> i32 {
|
||||
const QUERY: &str = "query {
|
||||
Viewer {
|
||||
id
|
||||
}
|
||||
}";
|
||||
let json = json!({ "query": QUERY });
|
||||
let resp = Request::builder()
|
||||
.method("POST")
|
||||
.uri("https://graphql.anilist.co/")
|
||||
.header("Content-Type", "application/json")
|
||||
.header("Accept", "application/json")
|
||||
.header("Authorization", format!("Bearer {}", token))
|
||||
.body(json.to_string())
|
||||
.unwrap()
|
||||
.send()
|
||||
.unwrap()
|
||||
.text();
|
||||
//println!("{}", resp);
|
||||
let regex = regex::Regex::new(r#"id":(.*?)}"#).unwrap();
|
||||
let resp: String = resp.as_ref().unwrap().to_string();
|
||||
let id = regex
|
||||
.captures(&resp)
|
||||
.unwrap()
|
||||
.get(1)
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.parse::<i32>()
|
||||
.unwrap();
|
||||
id
|
||||
}
|
||||
|
||||
pub fn get_user_anime_progress(anime_id: i32, token: &str) -> i32 {
|
||||
let user_id = get_user_id(&token);
|
||||
const QUERY: &str = "query ($user_id: Int, $media_id: Int) {
|
||||
MediaList (userId: $user_id, mediaId: $media_id, type: ANIME) {
|
||||
progress
|
||||
}
|
||||
}";
|
||||
let json = json!({
|
||||
"query": QUERY,
|
||||
"variables": {
|
||||
"user_id": user_id,
|
||||
"media_id": anime_id,
|
||||
}
|
||||
});
|
||||
let resp = Request::builder()
|
||||
.method("POST")
|
||||
.uri("https://graphql.anilist.co/")
|
||||
.header("Content-Type", "application/json")
|
||||
.header("Accept", "application/json")
|
||||
.header("Authorization", format!("Bearer {}", token))
|
||||
.body(json.to_string())
|
||||
.unwrap()
|
||||
.send()
|
||||
.unwrap()
|
||||
.text();
|
||||
//println!("{}", resp);
|
||||
let regex = regex::Regex::new(r#"progress":(.*?)}"#).unwrap();
|
||||
let resp: String = resp.as_ref().unwrap().to_string();
|
||||
//if resp contains "404"set progress to 1
|
||||
// else set progress to the number in the regex
|
||||
if resp.contains("404") {
|
||||
1
|
||||
} else {
|
||||
let progress = regex
|
||||
.captures(&resp)
|
||||
.unwrap()
|
||||
.get(1)
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.parse::<i32>()
|
||||
.unwrap();
|
||||
progress
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_anime_progress(anime_id: i32, anime: &str, progress: usize, token: &str) {
|
||||
const UPDATE: &str = "
|
||||
mutation ($mediaId: Int, $status: MediaListStatus, $progress: Int) {
|
||||
SaveMediaListEntry (mediaId: $mediaId, status: $status, progress: $progress) {
|
||||
id
|
||||
status
|
||||
progress
|
||||
}
|
||||
}
|
||||
";
|
||||
let json = json!({
|
||||
"query": UPDATE,
|
||||
"variables": {
|
||||
"mediaId": anime_id,
|
||||
"status": "CURRENT",
|
||||
"progress": progress
|
||||
}
|
||||
});
|
||||
let _resp = Request::builder()
|
||||
.method("POST")
|
||||
.uri("https://graphql.anilist.co/")
|
||||
.header("Content-Type", "application/json")
|
||||
.header("Accept", "application/json")
|
||||
.header("Authorization", format!("Bearer {}", token))
|
||||
.body(json.to_string())
|
||||
.unwrap()
|
||||
.send()
|
||||
.unwrap()
|
||||
.text();
|
||||
println!("updated progress of {} to episode {}", anime, progress);
|
||||
}
|
||||
Reference in New Issue
Block a user