open System
open System.IO
open Microsoft.WindowsAPICodePack.Dialogs
open System.Net
open System.Threading
let UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0"
let Referer = "https://www.pixiv.net/member_illust.php?mode="
let (|>>) x f = f x |> ignore ; x
let LogSystem =
new MailboxProcessor<ConsoleColor * string>(fun x ->
let rec loop count =
async{
let! c,s = x.Receive()
Console.ForegroundColor <- c
Console.WriteLine s
return! loop (count + 1)
}
loop 0)
let Log (e : string) =
LogSystem.Post(ConsoleColor.White,"[*] " + e)
let LogInfo (e : string) =
LogSystem.Post(ConsoleColor.DarkGray,"[i] " + e)
let LogError (e : string) =
LogSystem.Post(ConsoleColor.Red,"[!] " + e)
let LogFile path (e : string) =
let sw = new StreamWriter(path, true)
sw.WriteLine e
sw.Close()
let PathSeparator = Path.DirectorySeparatorChar.ToString()
let DirectoryPick _ =
let dialog = new CommonOpenFileDialog()
dialog.IsFolderPicker <- true
match dialog.ShowDialog() with
| CommonFileDialogResult.Ok -> dialog.FileName
| _ -> failwith "Empty Path"
type UrlType =
| Picture
| Pictures
| Zip
type Pid =
{ url : string;
urlType : UrlType }
let rec Input _ =
match Console.ReadLine().Trim().ToLower() with
| "" -> []
| s -> s::Input()
let PixivUrlDownloadAsync directory url =
async {
let path =
match url.urlType with
| UrlType.Pictures ->
(directory + PathSeparator + (Path.GetFileNameWithoutExtension url.url).Split('_').[0]
|>> (fun p ->
match Directory.Exists p with
| false -> Some(Directory.CreateDirectory p)
| _ -> None)) + PathSeparator
| _ -> directory + PathSeparator
+ Path.GetFileName url.url
use webClient = new WebClient()
webClient.Headers.Add("User-Agent",UserAgent)
webClient.Headers.Add("Referer",Referer + (match url.urlType with
| UrlType.Pictures -> "manga"
| _ -> "medium")
+ "&illust_id="
+ Path.GetFileNameWithoutExtension url.url)
webClient.DownloadProgressChanged.Add (fun e ->
Console.WriteLine(" [i] Progress " + e.ProgressPercentage.ToString() + " " + url.url))
webClient.Headers.Add(HttpRequestHeader.Cookie,"")
webClient.DownloadFileCompleted.Add (fun e ->
match e.Error with
| null ->
Console.WriteLine("[*] Completed " + url.url)
| error ->
webClient.CancelAsync()
Console.Write("[!] Error ")
Console.WriteLine(error)
Thread.Sleep(10000)
Console.WriteLine("[!] Redownloading " + url.url)
webClient.DownloadFileAsync(Uri(url.url), path))
Console.WriteLine("[*] Downloading " + url.url)
try
webClient.DownloadFileAsync(Uri(url.url), path)
with
| e ->
Console.WriteLine(e)
webClient.CancelAsync()
return true
}
let PixivUrlsDownloadAsync rawUrls =
rawUrls
|> Seq.ofList
|> Seq.map (fun raw ->
{url=raw;
urlType=
(match ('/'
|> raw.Split
|> List.ofArray
|> List.rev) with
| head::_ when head.Split('.').[1] = "zip" ->
UrlType.Zip
| head::_ when (rawUrls
|> List.exists (fun ru ->
("p0","p1")
|> head.Replace
|> ru.Contains)) ->
UrlType.Pictures
| _ -> UrlType.Picture)})
|> Seq.map (fun u ->
PixivUrlDownloadAsync (DirectoryPick()) u)
|> Async.Parallel
|> Async.RunSynchronously
let PixivUrlDownload directory url index length =
let path =
match url.urlType with
| UrlType.Pictures ->
(directory + PathSeparator + (Path.GetFileNameWithoutExtension url.url).Split('_').[0]
|>> (fun p ->
match Directory.Exists p with
| false -> Some(Directory.CreateDirectory p)
| _ -> None)) + PathSeparator
| _ -> directory + PathSeparator
+ Path.GetFileName url.url
let webClient = new WebClient()
webClient.Headers.Add("User-Agent",UserAgent)
webClient.Headers.Add("Referer",Referer + (match url.urlType with
| UrlType.Pictures -> "manga"
| _ -> "medium")
+ "&illust_id="
+ Path.GetFileNameWithoutExtension url.url)
webClient.Headers.Add(HttpRequestHeader.Cookie,"")
Log("[-] Downloading " + url.url)
try
webClient.DownloadFile(Uri(url.url), path)
LogInfo(" | " + (index + 1).ToString() + "/" + length.ToString() + " Succeed!")
with
| e ->
(" | " + Path.GetFileName url.url + " " + e.Message)
|>> LogError
|> LogFile (directory + PathSeparator + "Error.log")
let PixivUrlsDownload rawUrls =
let directory = DirectoryPick()
rawUrls
|> List.map (fun raw ->
{url=raw;
urlType=
(match ('/'
|> raw.Split
|> List.ofArray
|> List.rev) with
| head::_ when head.Split('.').[1] = "zip" ->
UrlType.Zip
| head::_ when (rawUrls
|> List.exists (fun ru ->
("p0","p1")
|> head.Replace
|> ru.Contains)) ->
UrlType.Pictures
| _ -> UrlType.Picture)})
|> List.iteri (fun i u ->
PixivUrlDownload directory u i rawUrls.Length)
[<STAThread>]
[<EntryPoint>]
let main argv=
LogSystem.Start()
match argv.Length with
| 0 -> Input() |> PixivUrlsDownload
| _ -> PixivUrlsDownload [argv.[0]]
Log "Done."
Console.Read() |> ignore
0