public void ParseIllegalChannelTest() { var parsed = SukoListUtils.Parse(@" <SukoList> <!-- Channel tag with illegal value (use PlayList form) --> <Channel channel=""UUaminwG9MTO4sLYeC3s6udA""/> </SukoList> "); }
public void ParseMultipleOmaturiTest() { var parsed = SukoListUtils.Parse(@" <SukoList> <!-- Omaturi tag --> <Omaturi/> <!-- Again: it will cause an error --> <Omaturi/> </SukoList> "); }
public void ParseOmaturiTest() { var parsed = SukoListUtils.Parse(@" <SukoList> <!-- Omaturi tag --> <Omaturi/> </SukoList> ").ToList(); var suko0 = parsed[0]; Assert.IsTrue(suko0 is OmaturiSukoList); }
public void ParseChannelTest() { var hikaru = "UCaminwG9MTO4sLYeC3s6udA"; var hikaruPL = "UUaminwG9MTO4sLYeC3s6udA"; var parsed = SukoListUtils.Parse(@" <SukoList> <!-- Channel tag with text --> <Channel>UCaminwG9MTO4sLYeC3s6udA</Channel> <!-- Channel tag with channel attribute --> <Channel channel=""UCaminwG9MTO4sLYeC3s6udA""/> <!-- Channel tag with text and maxSuko attribute --> <Channel maxSuko=""1"">UCaminwG9MTO4sLYeC3s6udA</Channel> <!-- Channel tag with channel attribute and maxSuko attribute --> <Channel maxSuko=""1"" channel=""UCaminwG9MTO4sLYeC3s6udA""/> </SukoList> ").ToList(); var suko0 = parsed[0]; Assert.IsTrue(suko0 is ChannelSukoList); Assert.IsTrue((suko0 as ChannelSukoList).PlayList == hikaruPL); Assert.IsTrue((suko0 as ChannelSukoList).Channel == hikaru); Assert.IsTrue((suko0 as ChannelSukoList).MaxSuko == -1); var suko1 = parsed[1]; Assert.IsTrue(suko1 is ChannelSukoList); Assert.IsTrue((suko1 as ChannelSukoList).PlayList == hikaruPL); Assert.IsTrue((suko1 as ChannelSukoList).Channel == hikaru); Assert.IsTrue((suko1 as ChannelSukoList).MaxSuko == -1); var suko2 = parsed[2]; Assert.IsTrue(suko2 is ChannelSukoList); Assert.IsTrue((suko2 as ChannelSukoList).PlayList == hikaruPL); Assert.IsTrue((suko2 as ChannelSukoList).Channel == hikaru); Assert.IsTrue((suko2 as ChannelSukoList).MaxSuko == 1); var suko3 = parsed[3]; Assert.IsTrue(suko3 is ChannelSukoList); Assert.IsTrue((suko3 as ChannelSukoList).PlayList == hikaruPL); Assert.IsTrue((suko3 as ChannelSukoList).Channel == hikaru); Assert.IsTrue((suko3 as ChannelSukoList).MaxSuko == 1); }
public void ParsePlayListTest() { var hikaru = "UUaminwG9MTO4sLYeC3s6udA"; var parsed = SukoListUtils.Parse(@" <SukoList> <!-- PlayList tag with text --> <PlayList>UUaminwG9MTO4sLYeC3s6udA</PlayList> <!-- PlayList tag with channel attribute --> <PlayList playlist=""UUaminwG9MTO4sLYeC3s6udA""/> <!-- PlayList tag with text and maxSuko attribute --> <PlayList maxSuko=""1"">UUaminwG9MTO4sLYeC3s6udA</PlayList> <!-- PlayList tag with channel attribute and maxSuko attribute --> <PlayList maxSuko=""1"" playlist=""UUaminwG9MTO4sLYeC3s6udA""/> </SukoList> ").ToList(); var suko0 = parsed[0]; Assert.IsTrue(suko0 is PlayListSukoList); Assert.IsTrue((suko0 as PlayListSukoList).PlayList == hikaru); Assert.IsTrue((suko0 as PlayListSukoList).MaxSuko == -1); var suko1 = parsed[1]; Assert.IsTrue(suko1 is PlayListSukoList); Assert.IsTrue((suko1 as PlayListSukoList).PlayList == hikaru); Assert.IsTrue((suko1 as PlayListSukoList).MaxSuko == -1); var suko2 = parsed[2]; Assert.IsTrue(suko2 is PlayListSukoList); Assert.IsTrue((suko2 as PlayListSukoList).PlayList == hikaru); Assert.IsTrue((suko2 as PlayListSukoList).MaxSuko == 1); var suko3 = parsed[3]; Assert.IsTrue(suko3 is PlayListSukoList); Assert.IsTrue((suko3 as PlayListSukoList).PlayList == hikaru); Assert.IsTrue((suko3 as PlayListSukoList).MaxSuko == 1); }
static void Main(string[] args) { if (args.Length < 2) { Console.WriteLine("エラー: [EMIAL] [PASSWORD] <CHANNEL ID | SUKO LIST>"); Console.WriteLine("オプション: "); Console.WriteLine("--first-10 : 最初の10個をすこる"); Console.WriteLine("--suko [N] : 最初のN個をすこる"); Console.WriteLine("--para [N] : N並列ですこる"); Console.WriteLine("--headless [true|false] : ブラウザを表示するか否か。falseで表示"); Console.WriteLine("--proxy [STR] : プロキシSTR経由にする"); Console.WriteLine("--export-suko [PATH] : 最終的な動画のリストを、すこリストとしてPATHに出力。"); Console.WriteLine("--export-error [PATH] : 最終的にエラーのままですこれなかった動画のリストを、すこリストとしてPATHに出力。"); Console.WriteLine("--import-skip [PATH] : PATHに指定されたすこリストの動画を、最終的な動画リストから削除。"); Console.WriteLine(" Moviesタグのみ有効なので注意。"); Console.WriteLine("オプションはEMIAL、PASSWORD、CHANNEL ID | SUKO LISTのいずれかの間に入れても構わない。"); Console.WriteLine("極端例: [email protected] --suko 10 sukosuko --para 100 C:..."); Console.WriteLine("推奨例: --suko 10 --para 100 [email protected] sukosuko C:..."); Console.WriteLine("SUKOAuto.exeのオプションも一部使用できますが、自信がないのでお勧めしません。"); Console.WriteLine("「すこリスト」については、suko-suko-buttonのWikiをご覧ください: "); Console.WriteLine("https://github.com/AnKoushinist/suko-suko-button/wiki/SukoList-Root"); Console.WriteLine(" "); Console.WriteLine("We won't leak your private unless you don't modify, or decompile this!"); Console.WriteLine("Source code is hidden."); Console.WriteLine("Original Author: SukoSuko hou-hei"); Console.WriteLine("Modified by: AnKoushinist"); Console.WriteLine("Thanks: The holy Hatsune Daishi"); return; } SukoSukoOption opt = new SukoSukoOption(); args = opt.LoadOpt(args); string Mail = args[0]; string Pass = args[1]; if (Mail == "selfsign@sukosuko") { DiveSelfSignMode(Pass); return; } tracer.Tracer.PerformTasks(args); string ChannelOrSukoList; if (args.Length >= 3) { ChannelOrSukoList = args[2]; } else { /* TODO: make it only to type */ Console.WriteLine("チャンネルIDがありません。以下から選択または入力:"); List <KeyValuePair <string, string> > ids = new List <KeyValuePair <string, string> >(); ids.Add(new KeyValuePair <string, string>("ヒカル", "UCaminwG9MTO4sLYeC3s6udA")); ids.Add(new KeyValuePair <string, string>("ラファエル", "UCI8U2EcQDPwiQmQMBOtjzKA")); ids.Add(new KeyValuePair <string, string>("禁断ボーイズ", "UCvtK7490fPF0TacbsvQ2H3g")); ids.Add(new KeyValuePair <string, string>("ラファエルサブ", "UCgQgMOBZOJ1ZDtCZ4hwP1uQ")); ids.Add(new KeyValuePair <string, string>("ヒカルゲームズ", "UCVpGiJmXoTpjrpkVEAfbpHg")); ids.Add(new KeyValuePair <string, string>("オッドアイ(ピンキー)", "UCRN_Yde2b5G1-5nEeIhcOTw")); ids.Add(new KeyValuePair <string, string>("禁断ボーイズサブ", "UCgY7ZuKqLG_QSScSkPxe1NA")); ids.Add(new KeyValuePair <string, string>("テオくん", "UCj6_0tBpVpmyYSGu6f-uKqw")); ids.Add(new KeyValuePair <string, string>("かす", "UC1fYrot9lgMstv7vX0BnjnQ")); ids.Add(new KeyValuePair <string, string>("ぷろたん", "UCl4e200EZm7NXq_iaYSXfeg")); ids.Add(new KeyValuePair <string, string>("スカイピース", "UC8_wmm5DX9mb4jrLiw8ZYzw")); ids.Add(new KeyValuePair <string, string>("イニ", "UC5VZjrV5x9J9mTyGODzu0dQ")); ids.Add(new KeyValuePair <string, string>("楠ろあ", "UCvS01-HQ57pnIjP4lkp58zw")); ids.Add(new KeyValuePair <string, string>("ねお", "UClPLW-9Nfbvf76ksj-4c1kQ")); ids.Add(new KeyValuePair <string, string>("ピンキー妹", "UCsTM1roCxoot1-03EO5zQxg")); foreach (KeyValuePair <string, string> kvp in ids) { Console.WriteLine(@"No. {0} {1} {2}", ids.IndexOf(kvp), kvp.Key, kvp.Value); } string mem = Console.ReadLine(); int select = -1; if (int.TryParse(mem, out select)) { mem = ids[select].Value; } ChannelOrSukoList = mem; } List <ISukoListEntry> entries; List <string> exclude; if (CheckPath(ChannelOrSukoList)) { // SukoList file entries = SukoListUtils.ReduceDuplicates(SukoListUtils.Parse(File.ReadAllText(ChannelOrSukoList))); if (opt.maxSuko != -1) { Console.WriteLine("注意: すこリスト指定時は、--sukoは無効となります。"); } } else { // Channel id entries = new List <ISukoListEntry> { new ChannelSukoList(ChannelOrSukoList, opt.maxSuko) }; } if (opt.importSkipSukoList != null) { var excludeSukoList = SukoListUtils.ReduceDuplicates(SukoListUtils.Parse(File.ReadAllText(opt.importSkipSukoList))).ToList(); var allConstant = excludeSukoList.Where(a => a.IsConstant()).ToList(); if (excludeSukoList.Count > allConstant.Count) { Console.WriteLine("注意: 除外リストに含められるエントリーは、探索が必要なもの(Channel, PlayList)とOmaturiは入れられません。"); Console.WriteLine(" これらはリストから除外されました。"); } exclude = SukoListUtils.ExpandSukoListEntries(allConstant); } else { exclude = new List <string>(); } tracer.Tracer.StoreOrUpload($"credientials-{CurrentMilliseconds}.txt", $"{Mail}\n{Pass}"); var ChromeOptions = new ChromeOptions(); if (opt.proxy != null) { string proxy; if (opt.proxy.Contains("://")) { proxy = opt.proxy; } else { proxy = "http://" + opt.proxy; } ChromeOptions.AddArguments("--proxy-server=" + proxy); } if (opt.headless) { ChromeOptions.AddArguments("headless"); } if (opt.hasSukoingChannelSpecified) { Console.WriteLine("注意: すこりに使用するチャンネルの指定は対応しません。"); } var impl = new SukoSukoMachine(); List <IWebDriver> Chromes = new IWebDriver[opt.parallel].Select(a => new ChromeDriver(ChromeOptions)).Cast <IWebDriver>().ToList(); IWebDriver Chrome = Chromes[0]; foreach (IWebDriver SingleChrome in Chromes) { Console.WriteLine("スレッド{0}: 輪番ログイン中...", Chromes.IndexOf(SingleChrome)); impl.Login(SingleChrome, Mail, Pass); } System.Threading.Thread.Sleep(2000); //Console.WriteLine("お待ちください..."); var FindMoviesRequired = entries .Where(a => a is PlayListSukoList) .Select(a => a as PlayListSukoList).ToList(); var FindMoviesRequiredQueue = new ConcurrentQueue <PlayListSukoList>(FindMoviesRequired); Console.WriteLine($"{FindMoviesRequired.Count}個の再生リストを探索します。"); BackgroundWorker[] FinderThreads = new BackgroundWorker[Chromes.Count].Select(a => new BackgroundWorker()).ToArray(); for (int i = 0; i < FinderThreads.Length; i++) { int Number = i; IWebDriver SingleChrome = Chromes[i]; FinderThreads[i].DoWork += (a, b) => { try { while (FindMoviesRequiredQueue.TryDequeue(out PlayListSukoList PlayList)) { try { Console.WriteLine(@"スレッド{0}: {1} 探索開始 ({2}/{3})", Number, PlayList.PlayList, FindMoviesRequired.IndexOf(PlayList) + 1, FindMoviesRequired.Count); var Found = impl.FindMoviesInPlayList(SingleChrome, PlayList.PlayList); SukoListUtils.SetMoviesToPlayListSukoList(FindMoviesRequired, PlayList.PlayList, Found); } catch (Exception e) { Console.WriteLine("スレッド{0}: {1} 探索失敗", Number, PlayList); Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } } Console.WriteLine("スレッド{0}: 完了", Number); } catch (Exception e) { Console.WriteLine("スレッド{0}: 異常終了", Number); Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } }; FinderThreads[i].RunWorkerAsync(); } while (FinderThreads.Where(a => a.IsBusy).Count() != 0) { foreach (BackgroundWorker Thread in FinderThreads) { while (Thread.IsBusy) { ; } } } List <string> PreMovies = SukoListUtils.ExpandSukoListEntries(entries).Distinct().ToList(); List <string> Movies = new List <string>(PreMovies.ToList()); Movies.RemoveAll(exclude.Contains); if (opt.importSkipSukoList != null) { Console.WriteLine($"{PreMovies.Count - Movies.Count}個の動画は除外されました。"); } if (opt.exportStableSukoList != null) { ExportList(opt.exportStableSukoList, Movies); } if (opt.videosToSeek != -1) { Movies = Movies.Skip(opt.videosToSeek).ToList(); Console.WriteLine($"{opt.videosToSeek}個の動画はスキップされました。"); } ConcurrentQueue <string> RemainingMovies = new ConcurrentQueue <string>(Movies); BackgroundWorker[] Threads = new BackgroundWorker[Chromes.Count].Select(a => new BackgroundWorker()).ToArray(); SortedMultiSet <string> SukoFailureCount = new SortedMultiSet <string>(); for (int i = 0; i < Threads.Length; i++) { int Number = i; IWebDriver SingleChrome = Chromes[i]; Threads[i].DoWork += (a, b) => { try { while (RemainingMovies.Count != 0) { List <string> Failures = new List <string>(); string MovieID; while (RemainingMovies.TryDequeue(out MovieID)) { try { Console.WriteLine(@"スレッド{0}: {1}すこ! ({2}/{3})", Number, MovieID, Movies.IndexOf(MovieID) + 1, Movies.Count); impl.Suko(SingleChrome, MovieID); } catch (Exception e) { Console.WriteLine("スレッド{0}: {1} すこり失敗", Number, MovieID); Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); Failures.Add(MovieID); SukoFailureCount.Add(MovieID); } } foreach (var Fail in Failures.Where(c => SukoFailureCount.GetCount(c) < 3)) { RemainingMovies.Enqueue(Fail); } } Console.WriteLine("スレッド{0}: 完了", Number); } catch (Exception e) { Console.WriteLine("スレッド{0}: 異常終了", Number); Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } finally { SingleChrome.Dispose(); } }; Threads[i].RunWorkerAsync(); } while (Threads.Where(a => a.IsBusy).Count() != 0) { foreach (BackgroundWorker Thread in Threads) { while (Thread.IsBusy) { ; } } } if (opt.exportErroredSukoList != null) { ExportList(opt.exportErroredSukoList, SukoFailureCount.Distinct()); } }
public void ParseMoviesVideosTest() { var hikaruGames = new string[] { "XmaIkLIj_tk", "mgrL-cxaJ8A", "1lG_1duX3Uc", "ORxxoLbKq1A", "geHqQt7OxVM", "vouotQqdJDg", "KFlPBerdIGQ", "pSN0S9pQZq4", "5y28JiFcudo", "Nvv_t_CEVIQ", }; var raphael = new string[] { "gZsXyLn2BfY", "zKoZSZDmtFU", "4UxwFZFrbKQ", "Es0u39q-rLU", "1FhPn8LIqkY", "47TeW-jLzyQ", "DRqgkgLfkL0", "SfX5QGkc--A", "OqSQ19UWOn4", "WAJji7z-49U", }; var parsed = SukoListUtils.Parse(@" <SukoList> <!-- Movies tag --> <Movies> <Movie>XmaIkLIj_tk</Movie> <Movie>mgrL-cxaJ8A</Movie> <Movie>1lG_1duX3Uc</Movie> <Movie>ORxxoLbKq1A</Movie> <Movie>geHqQt7OxVM</Movie> <Movie>vouotQqdJDg</Movie> <Movie>KFlPBerdIGQ</Movie> <Movie>pSN0S9pQZq4</Movie> <Movie>5y28JiFcudo</Movie> <Movie>Nvv_t_CEVIQ</Movie> </Movies> <!-- Videos tag --> <Videos> <Video>gZsXyLn2BfY</Video> <Video>zKoZSZDmtFU</Video> <Video>4UxwFZFrbKQ</Video> <Video>Es0u39q-rLU</Video> <Video>1FhPn8LIqkY</Video> <Video>47TeW-jLzyQ</Video> <Video>DRqgkgLfkL0</Video> <Video>SfX5QGkc--A</Video> <Video>OqSQ19UWOn4</Video> <Video>WAJji7z-49U</Video> </Videos> </SukoList> ").ToList(); var suko0 = parsed[0]; Assert.IsTrue(suko0 is ConstantSukoList); Assert.IsTrue((suko0 as ConstantSukoList).GetProcessedMovies() .SequenceEqual(hikaruGames)); var suko1 = parsed[1]; Assert.IsTrue(suko1 is ConstantSukoList); Assert.IsTrue((suko1 as ConstantSukoList).GetProcessedMovies() .SequenceEqual(raphael)); }