Files
EHDownloader/EHDownloader/Form1.cs

236 lines
8.0 KiB
C#

using HtmlAgilityPack;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace EHDownloader
{
public partial class Form1 : System.Windows.Forms.Form
{
string baseFolder;
string _folder;
static System.Text.RegularExpressions.Regex _regex_url = new System.Text.RegularExpressions.Regex(@"^https?://e-hentai.org/g/[^/]*/[^/]*/?$",
System.Text.RegularExpressions.RegexOptions.Compiled);
static System.Text.RegularExpressions.Regex _ex_regex_url = new System.Text.RegularExpressions.Regex(@"^https?://exhentai.org/g/[^/]*/[^/]*/?$",
System.Text.RegularExpressions.RegexOptions.Compiled);
System.Threading.Thread _clipboardMonitorThread;
bool _clipboardMonitorThreadWorking = false;
DbContext _dbContext;
public Form1()
{
InitializeComponent();
baseFolder = Properties.Settings.Default.BaseFolder;
resetFolder();
_dbContext = new DbContext();
_clipboardMonitorThread = new System.Threading.Thread(clipboardMonitorProc);
_clipboardMonitorThread.SetApartmentState(System.Threading.ApartmentState.STA);
_clipboardMonitorThread.Start();
}
protected override void OnClosing(CancelEventArgs e)
{
base.OnClosing(e);
_clipboardMonitorThreadWorking = false;
}
bool isEhUrl(string url)
{
return _regex_url.IsMatch(url) || _ex_regex_url.IsMatch(url);
}
private void clipboardMonitorProc()
{
_clipboardMonitorThreadWorking = true;
string lastText = string.Empty;
while (!IsDisposed && _clipboardMonitorThreadWorking)
{
try
{
var clipboardText = Clipboard.GetText();
if (lastText != clipboardText &&
!string.IsNullOrWhiteSpace(clipboardText))
{
lastText = clipboardText;
var lines = clipboardText.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
foreach (var url in lines)
{
if (isEhUrl(url))
{
BeginInvoke(new Action(() => AddTask(url)));
}
}
}
System.Threading.Thread.Sleep(1000);
}
catch (Exception)
{
}
}
}
private void btn_Add_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(txt_url.Text))
{
AddTask(txt_url.Text);
}
// await Book.DownloadBookAsync("https://e-hentai.org/g/1464116/fa326cdb2b/", @"Z:\");
//await Book.GetBookAsync("https://e-hentai.org/g/1464871/56158ca706/");
// await Book.GetBookAsync("https://e-hentai.org/g/1463748/3a40615ef7");
// Book.GetBook("https://e-hentai.org/g/1411798/ac15344281/");
}
bool downloading = false;
// object downloadingLck = new object();
// System.Threading.Mutex downloadingMutex = new System.Threading.Mutex(true);
private async void AddTask(string url)
{
if (!isEhUrl(url)) return;
if (lv_Tasks.Items.ContainsKey(url)) return;
// if (_dbContext.BookIsExists(url)) return;
await newTask(url);
}
private async Task newTask(string url)
{
BookStates? newBookState = _dbContext.QueryBookState(url);
if (newBookState.IsCompleted())
{
// 已完成
return;
}
Book book = new Book(url, _folder);
if (!newBookState.HasValue)
_dbContext.InsertBook(book);
else
_dbContext.UpdateBook(book);
ListViewItem lvi = new ListViewItem(url) { Name = url };
lvi.SubItems.Add("Wait");
lvi.Text = url;
lvi.Tag = book;
lv_Tasks.Items.Add(lvi);
await TryStartTask(lvi);
}
private async Task TryStartTask()
=> await TryStartTask(lv_Tasks.Items[0]);
private async Task TryStartTask(ListViewItem lvi)
{
if (downloading)
return;
try
{
downloading = true;
Book book = (Book)lvi.Tag;
bool running = true;
while (running)
{
lvi.SubItems[1].Text = book.State.GetDescription();
switch (book.State)
{
case BookStates.Wait:
await book.FetchAsync();
_dbContext.UpdateBook(book);
break;
case BookStates.FetchCompleted:
await book.DownloadBookAsync(new Progress<DownloadProgressInfo>(
(info) => lvi.SubItems[1].Text = $"下載中 {info.PageNumber}/{info.PageCount}"));
_dbContext.UpdateBook(book);
break;
case BookStates.DownloadCompleted:
await book.CompressAsync();
_dbContext.UpdateBook(book);
goto default;
case BookStates.Compressed:
case BookStates.LoadFailed:
case BookStates.FetchTitleFailed:
case BookStates.FetchPageSetFailed:
case BookStates.FetchPageLinkFailed:
case BookStates.DownloadFinishedButSomePageError:
default:
var i = lv_Tasks.Items.IndexOf(lvi) + 1;
if (i >= lv_Tasks.Items.Count) return;
lvi = lv_Tasks.Items[i];
book = (Book)lvi.Tag;
break;
}
}
}
finally
{
downloading = false;
}
}
private async void Btn_Retry_Click(object sender, EventArgs e)
{
if (downloading)
return;
for (int i = 0; i < lv_Tasks.Items.Count; i++)
{
var lvi = lv_Tasks.Items[i];
var book = (Book)lvi.Tag;
switch (book.State)
{
case BookStates.Wait:
case BookStates.FetchCompleted:
case BookStates.DownloadCompleted:
case BookStates.Compressed:
default:
continue;
case BookStates.LoadFailed:
case BookStates.FetchTitleFailed:
case BookStates.FetchPageSetFailed:
case BookStates.FetchPageLinkFailed:
book.State = BookStates.Wait;
continue;
case BookStates.DownloadFinishedButSomePageError:
book.State = BookStates.FetchCompleted;
continue;
}
}
await TryStartTask();
}
private void setFolder(string folder)
{
_folder = folder;
txt_folder.Text = folder;
}
void resetFolder()
{
setFolder(System.IO.Path.Combine(baseFolder, DateTime.Today.ToString("yyMMdd")));
}
private void btn_resetFolder_Click(object sender, EventArgs e)
{
resetFolder();
}
}
}