예제 #1
0
        private static void ManageTracker(TorrentHandler H)
        {
            Console.Clear();
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("Adding and removing trackers is not supported on MonoTorrent");
            Console.ResetColor();
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("List of public trackers we know:");
            if (TorrentHandler.PublicTrackers != null)
            {
                foreach (var T in TorrentHandler.PublicTrackers)
                {
                    Console.WriteLine(T);
                }
            }
            else
            {
                Console.WriteLine("none (Download of list failed)");
            }
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("Trackers registered for this torrent");
            foreach (var T in H.GetTracker())
            {
                Console.WriteLine("{0,-30} {1}", T.Status, T.Uri);
            }
            Console.Write("Press any key to go back");
            Console.ReadKey();

            /*
             * bool cont = true;
             * while (cont)
             * {
             *  Console.Clear();
             *  Console.SetCursorPosition(0, Console.WindowHeight - 1);
             *  Console.Write("Enter a new tracker URL to add or nothing to go back");
             *  Console.SetCursorPosition(0, 0);
             *  foreach (var T in H.GetTracker())
             *  {
             *      Console.WriteLine(T);
             *  }
             *  var URL = Console.ReadLine();
             *  if (!string.IsNullOrEmpty(URL))
             *  {
             *      try
             *      {
             *          H.AddTracker(new Uri(URL));
             *      }
             *      catch
             *      {
             *          //NOOP
             *      }
             *  }
             *  else
             *  {
             *      cont = false;
             *  }
             * }
             * //*/
        }
예제 #2
0
        public static int Main(string[] args)
        {
            LaunchedFromCmd = (ParentProcessUtilities.GetParentProcessName().ToLower() == Environment.ExpandEnvironmentVariables("%COMSPEC%").ToLower());
#if DEBUG
            args = new string[] {
                //2018-04-18-raspbian-stretch-lite.zip
                "05E76C8B1795CE49E203BE4C39E378F7A97CBED5"
            };
#endif
            Console.WriteLine("Grabbing public trackers");
            using (var CL = new HttpClient())
            {
                CL.DefaultRequestHeaders.Add("User-Agent", "AyrA-QuickTorrent/1.0");
                try
                {
                    var Result = CL
                                 .GetAsync("https://cable.ayra.ch/tracker/list.php?prot[]=https&prot[]=http")
                                 .Result;
                    if (Result.IsSuccessStatusCode)
                    {
                        TorrentHandler.PublicTrackers = new List <string>(Result
                                                                          .Content.ReadAsStringAsync().Result.Split('\n')
                                                                          .Select(m => m.Trim())
                                                                          .Where(m => !string.IsNullOrEmpty(m))
                                                                          .Distinct());
                    }
                    else
                    {
                        throw new Exception("Unable to download Trackers");
                    }
                }
                catch
                {
                    Console.WriteLine("Unable to download public tracker list");
                    Thread.Sleep(5000);
                }
            }


            Handler = new List <TorrentHandler>();
            //Allows adding torrents via pipe
            Pipe.HashAdded += delegate(string Hash)
            {
                var Entry = GetHandler(Hash);
                if (Entry != null)
                {
                    lock (Handler)
                    {
                        //only add if not existing already
                        if (!Handler.Any(m => m != null && m.InfoHash == Entry.InfoHash))
                        {
                            Handler.Add(Entry);
                        }
                    }
#if !DEBUG
                    Entry.Start();
#endif
                }
            };

            #region Initial Download Creator
            if (args.Length > 0)
            {
                if (!args.Contains("/?"))
                {
                    foreach (var arg in args)
                    {
                        var HandlerEntry = GetHandler(arg);
                        if (HandlerEntry == null)
                        {
                            Console.Error.WriteLine("Invalid Argument. Only file names, magnet links and hashes are supported.");
                            WaitForExit();
                            return(RET.ARGUMENT_ERROR);
                        }
                        else
                        {
                            Handler.Add(HandlerEntry);
                        }
                    }
                }
                else
                {
                    Console.Error.WriteLine(@"QuickTorrent.exe [TorrentFile [...]] [MagnetLink [...]] [InfoHash [...]]

TorrentFile  - Torrent file to download
MagnetLink   - Magnet link to download that can be found in the DHT network
InfoHash     - SHA1 hash of a torrent that can be found in the DHT network

Without arguments the application tries to interpret its file name as a hash.");
                    WaitForExit();
                    return(RET.HELP);
                }
            }
            else
            {
                var Hash = Process.GetCurrentProcess().MainModule.FileName.Split(Path.DirectorySeparatorChar).Last().Split('.')[0];
                if (ValidHex(Hash))
                {
                    Handler.Add(new TorrentHandler(ParseHash(Hash)));
                }
                else
                {
                    Console.Error.WriteLine("No arguments given and file name not valid Infohash");
                    WaitForExit();
                    return(RET.NAME_ERROR);
                }
            }
            #endregion

            for (int i = 0; i < Handler.Count; i++)
            {
                if (Handler[i] == null)
                {
                    Handler.RemoveAt(i--);
                }
            }
            //If we can't start a pipe it is likely that there is already an instance running
            if (!Pipe.StartPipe())
            {
                //Try to transfer all downloads
                if (!Handler.Select(m => Pipe.SendViaPipe(m.InfoHash)).ToArray().Any(m => m))
                {
                    //We can neither start the pipe nor transfer requests to another client.
                    Console.Error.WriteLine("Unable to start pipe or transfer downloads to other instance. Adding torrents at Runtime will be unavailable");
                    Thread.Sleep(5000);
                }
                else
                {
                    //Requests transferred. Exit application
                    return(RET.TRANSFER);
                }
            }

            Console.Clear();

#if !DEBUG
            foreach (var H in Handler)
            {
                H.Start();
            }
#endif
            //Thread will exit if set to false
            bool cont = true;
            //Exists the Wait loops and updates the screen once
            bool update = false;
            //Completely redraws the screen once
            bool redraw = false;
            //Selected Torrent
            int    Selected = 0;
            Thread T        = new Thread(delegate()
            {
                #region Torrent Loop
                const int NAMELENGTH = 30;
                while (cont && Handler.Count(m => m != null) > 0)
                {
                    Console.Title = $"QuickTorrent: {Handler.Count(m => m != null)} transfers";

                    //Pause this thread while in the tracker selection
                    while (CurrentMode == DisplayMode.Tracker)
                    {
                        Thread.Sleep(100);
                    }

                    int CurrentSelected = Selected;
                    if (redraw)
                    {
                        Console.Clear();
                        redraw = false;
                    }
                    else
                    {
                        Console.SetCursorPosition(0, 0);
                    }
                    lock (Handler)
                    {
                        //var H = Handler[j];
                        switch (CurrentMode)
                        {
                        case DisplayMode.Overview:
                            for (int j = 0; j < Handler.Count; j++)
                            {
                                if (Handler[j] != null)
                                {
                                    string Name = Handler[j].TorrentName == null ? "" : Handler[j].TorrentName;
                                    //Subtraction is: name length, percentage and the 4 spaces
                                    var LineMap = new string(StretchMap(Handler[j].Map, Console.BufferWidth - NAMELENGTH - 8).Select(m => m ? '█' : '░').ToArray());
                                    if (Name.Length > NAMELENGTH)
                                    {
                                        Name = Name.Substring(Name.Length - NAMELENGTH, NAMELENGTH);
                                    }
                                    Console.ForegroundColor = ConsoleColor.White;
                                    Console.Error.Write("{0} ", Selected == j ? '►' : ' ');
                                    Console.ForegroundColor = StateToColor(Handler[j].State);
                                    switch (Handler[j].State)
                                    {
                                    case TorrentState.Metadata:
                                        break;

                                    case TorrentState.Hashing:
                                        break;

                                    case TorrentState.Downloading:
                                        if (Handler[j].HasAllPieces && (int)Handler[j].Progress == 100)
                                        {
                                            Handler[j].Stop();
                                            Handler[j].SaveRecovery();
                                            Handler[j].Start();
                                        }
                                        break;

                                    case TorrentState.Seeding:
                                        if (!Handler[j].HasAllPieces)
                                        {
                                            //Assume that this torrent is complete
                                            Handler[j].SetComplete();
                                        }
                                        break;

                                    case TorrentState.Stopped:
                                    case TorrentState.Stopping:
                                        break;

                                    case TorrentState.Paused:
                                        break;

                                    default:
                                        break;
                                    }
                                    Console.Error.Write("{0,-" + NAMELENGTH + "} {1,3}% {2}", Name, (int)Handler[j].Progress, LineMap);
                                }
                            }

                            Console.ResetColor();
                            Console.Error.WriteLine("[↑↓] Select | [SPACE] Start/Stop | [ENTER] Detail | [T] Tracker | [DEL] Delete | [ESC] Exit");
                            break;

                        case DisplayMode.Details:
                            Console.ForegroundColor = StateToColor(Handler[Selected].State);
                            Console.Error.WriteLine("".PadRight(Console.BufferWidth * 7));
                            Console.SetCursorPosition(0, 0);
                            Console.Error.WriteLine(@"Transfer Detail

Name:     {0}
Hash:     {1}
Files:    {2,-5} ({3})
State:    {4,-20}
Progress: {5:0.00}%",
                                                    Handler[Selected].TorrentName.PadRight(Console.BufferWidth - 11),
                                                    Handler[Selected].InfoHash,
                                                    Handler[Selected].Files,
                                                    NiceSize(Handler[Selected].TotalSize),
                                                    Handler[Selected].State,
                                                    Math.Round(Handler[Selected].Progress, 2));
                            var FullMap = new string(StretchMap(Handler[Selected].Map, Console.BufferWidth * (Console.WindowHeight - 8)).Select(m => m ? '█' : '░').ToArray());
                            Console.Error.Write("{0}[ESC] Back | [T] Tracker", FullMap);
                            Console.ResetColor();
                            break;

                        case DisplayMode.Tracker:
                            //Don't do anything on tracker, this is done outside of the update loop
                            break;

                        default:
                            throw new NotImplementedException($"Unimplemented Mode: {CurrentMode}");
                        }
                    }

                    int i = 0;
                    //This makes the thread responsive to exit calls (cont=false)
                    while (cont && i < UI_UPDATE_INTERVAL && CurrentSelected == Selected && !update)
                    {
                        i += 100;
                        Thread.Sleep(100);
                    }
                    update = false;
                }
                #endregion
            })
            {
                IsBackground = true, Name = "StatusLoop"
            };
            T.Start();

            #region Keyboard Handler
            while (cont && Handler.Count(m => m != null) > 0)
            {
                var H = Handler[Selected];
                switch (Console.ReadKey(true).Key)
                {
                case ConsoleKey.T:
                    var OldMode = CurrentMode;
                    CurrentMode = DisplayMode.Tracker;
                    ManageTracker(H);
                    CurrentMode = OldMode;
                    redraw      = update = true;
                    break;

                case ConsoleKey.Escape:
                    if (CurrentMode == DisplayMode.Details || CurrentMode == DisplayMode.Tracker)
                    {
                        CurrentMode = DisplayMode.Overview;
                        redraw      = update = true;
                    }
                    else if (CurrentMode == DisplayMode.Overview)
                    {
                        cont = false;
                    }
                    break;

                case ConsoleKey.UpArrow:
                    if (--Selected < 0)
                    {
                        Selected = 0;
                    }
                    update = true;
                    break;

                case ConsoleKey.DownArrow:
                    if (++Selected >= Handler.Count)
                    {
                        Selected = Handler.Count - 1;
                    }
                    update = true;
                    break;

                case ConsoleKey.Spacebar:
                    if (H.State == TorrentState.Stopped || H.State == TorrentState.Error)
                    {
                        H.Start();
                        update = true;
                    }
                    else if (H.State != TorrentState.Stopping &&
                             H.State != TorrentState.Error &&
                             H.State != TorrentState.Paused)
                    {
                        H.Stop();
                        update = true;
                    }
                    break;

                case ConsoleKey.Delete:
                    lock (Handler)
                    {
                        H.Stop();
                        H.ClearRecovery();
                        H.Dispose();
                        Handler.Remove(H);
                    }
                    if (Handler.Count > 0)
                    {
                        if (Selected >= Handler.Count)
                        {
                            Selected = Handler.Count - 1;
                        }
                    }
                    else
                    {
                        cont = false;
                    }
                    update = redraw = true;
                    break;

                case ConsoleKey.Enter:
                    CurrentMode = DisplayMode.Details;
                    update      = true;
                    break;
                }
            }
            #endregion

            T.Join();
            Console.Error.WriteLine("Exiting...");
            TorrentHandler.StopAll();
            foreach (var H in Handler.Where(m => m != null))
            {
                Console.Error.Write('.');
                H.SaveRecovery();
                H.Dispose();
            }
            TorrentHandler.SaveDhtNodes();
            Console.Error.WriteLine("DONE. Cleaning up...");
            return(RET.SUCCESS);
        }
예제 #3
0
        public static int Main(string[] args)
        {
            LaunchedFromCmd = (ParentProcessUtilities.GetParentProcessName().ToLower() == Environment.ExpandEnvironmentVariables("%COMSPEC%").ToLower());
#if DEBUG
            args = new string[] {
                /* <-- Use two slashes to swap the hashes below
                 *
                 * //Debian DVD images
                 * "40F90995A1C16A1BF454D09907F57700F3E8BD64",
                 * "86F72E6B829C7E2D089B5CF0D1DED09122E65CA4",
                 * "E355364EBEB5838B27705C68F85B20A950110B8F"
                 *
                 * /*/

                //Debian CD images
                "A7055D06E5A8F7F816EC01AC7F7F5243D3CB008F",
                "63515D99E2A99E79526E35C9A39A1DFD843027A0",
                "297ACD1A5D6BA3E1AB881E27ACB73843A6E81430",
                "9E2C34C3FD30D25FED9A23D93FCC69AE546C1D10",
                "A887676B3E790DD28A92772B776199529F477762",
                "7980011D310EB8B6F8F5F593E82F83510901CE1C",
                "90C52B25375F12432D504BAD7F587E5543F22FDA",
                "1DADBB8451DDDF23ADB276D0C887EF60EC49989E"
                //*/
            };
#endif
            Handler = new List <TorrentHandler>();
            if (args.Length > 0)
            {
                if (!args.Contains("/?"))
                {
                    foreach (var arg in args)
                    {
                        if (arg.ToLower().StartsWith("magnet:"))
                        {
                            Handler.Add(new TorrentHandler(ParseLink(arg)));
                        }
                        else if (File.Exists(arg))
                        {
                            Handler.Add(new TorrentHandler(ParseTorrent(arg)));
                        }
                        else if (ValidHex(arg))
                        {
                            Handler.Add(new TorrentHandler(ParseHash(arg)));
                        }
                        else
                        {
                            Console.Error.WriteLine("Invalid Argument. Only file names, magnet links and hashes are supported.");
                            WaitForExit();
                            return(RET.ARGUMENT_ERROR);
                        }
                    }
                }
                else
                {
                    Console.Error.WriteLine(@"QuickTorrent.exe [TorrentFile [...]] [MagnetLink [...]] [InfoHash [...]]

TorrentFile  - Torrent file to download
MagnetLink   - Magnet link to download that can be found in the DHT network
InfoHash     - SHA1 hash of a torrent that can be found in the DHT network

Without arguments the application tries to interpret its file name as a hash.");
                    WaitForExit();
                    return(RET.HELP);
                }
            }
            else
            {
                var Hash = Process.GetCurrentProcess().MainModule.FileName.Split(Path.DirectorySeparatorChar).Last().Split('.')[0];
                if (ValidHex(Hash))
                {
                    Handler.Add(new TorrentHandler(ParseHash(Hash)));
                }
                else
                {
                    Console.Error.WriteLine("No arguments given and file name not valid Infohash");
                    WaitForExit();
                    return(RET.NAME_ERROR);
                }
            }
            for (int i = 0; i < Handler.Count; i++)
            {
                if (Handler[i] == null)
                {
                    Handler.RemoveAt(i--);
                }
            }
            TorrentHandler.StartAll();

            Console.Title = $"QuickTorrent: {Handler.Count(m => m != null)} transfers";

            bool   cont         = true;
            bool   update       = false;
            int    Selected     = 0;
            bool   RenderDetail = false;
            Thread T            = new Thread(delegate()
            {
                const int NAMELENGTH = 30;
                while (cont)
                {
                    int CurrentSelected = Selected;
                    Console.SetCursorPosition(0, 0);
                    if (!RenderDetail)
                    {
                        for (int j = 0; j < Handler.Count; j++)
                        {
                            var H       = Handler[j];
                            string Name = H.TorrentName == null ? "" : H.TorrentName;
                            //Subtraction is: name length, percentage and the 4 spaces
                            var Map = new string(StretchMap(H.Map, Console.BufferWidth - NAMELENGTH - 8).Select(m => m ? '█' : '░').ToArray());
                            if (Name.Length > NAMELENGTH)
                            {
                                Name = Name.Substring(Name.Length - NAMELENGTH, NAMELENGTH);
                            }
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Error.Write("{0} ", Selected == j ? '►' : ' ');
                            Console.ForegroundColor = StateToColor(H.State);
                            switch (H.State)
                            {
                            case TorrentState.Metadata:
                                break;

                            case TorrentState.Hashing:
                                break;

                            case TorrentState.Downloading:
                                if (H.HasAllPieces && (int)H.Progress == 100)
                                {
                                    H.Stop();
                                    H.SaveRecovery();
                                    H.Start();
                                }
                                break;

                            case TorrentState.Seeding:
                                if (!H.HasAllPieces)
                                {
                                    //Assume that this torrent is complete
                                    H.SetComplete();
                                }
                                break;

                            case TorrentState.Stopped:
                            case TorrentState.Stopping:
                                break;

                            case TorrentState.Paused:
                                break;

                            default:
                                break;
                            }

                            Console.Error.Write("{0,-" + NAMELENGTH + "} {1,3}% {2}", Name, (int)H.Progress, Map);
                        }
                        Console.ResetColor();
                        Console.Error.WriteLine("[↑↓] Select | [SPACE] Start/Stop | [ENTER] Detail | [ESC] Exit");
                    }
                    else
                    {
                        var H = Handler[Selected];
                        Console.ForegroundColor = StateToColor(H.State);
                        Console.Error.WriteLine(@"Transfer Detail

Name:     {0}
Hash:     {1}
Files:    {2} ({3})
State:    {4,-20}
Progress: {5:0.00}%", H.TorrentName, H.InfoHash, H.Files, NiceSize(H.TotalSize), H.State, Math.Round(H.Progress, 2));
                        var Map = new string(StretchMap(H.Map, Console.BufferWidth * (Console.WindowHeight - 8)).Select(m => m ? '█' : '░').ToArray());
                        Console.Error.Write("{0}[ESC] Back", Map);
                        Console.ResetColor();
                    }

                    int i = 0;
                    //This makes the thread responsive to exit calls (cont=false)
                    while (cont && i < UI_UPDATE_INTERVAL && CurrentSelected == Selected && !update)
                    {
                        i += 100;
                        Thread.Sleep(100);
                    }
                    update = false;
                }
            })
            {
                IsBackground = true, Name = "Status"
            };
            T.Start();

            while (cont)
            {
                var H = Handler[Selected];
                switch (Console.ReadKey(true).Key)
                {
                case ConsoleKey.Escape:
                    if (RenderDetail)
                    {
                        RenderDetail = false;
                        Console.Clear();
                        update = true;
                    }
                    else
                    {
                        cont = false;
                    }
                    break;

                case ConsoleKey.UpArrow:
                    if (--Selected < 0)
                    {
                        Selected = 0;
                    }
                    else if (RenderDetail)
                    {
                        Console.Clear();
                    }
                    break;

                case ConsoleKey.DownArrow:
                    if (++Selected >= Handler.Count)
                    {
                        Selected = Handler.Count - 1;
                    }
                    else if (RenderDetail)
                    {
                        Console.Clear();
                    }
                    break;

                case ConsoleKey.Spacebar:
                    if (H.State == TorrentState.Stopped)
                    {
                        H.Start();
                        update = true;
                    }
                    else if (H.State != TorrentState.Stopping &&
                             H.State != TorrentState.Error &&
                             H.State != TorrentState.Paused)
                    {
                        H.Stop();
                        update = true;
                    }
                    break;

                case ConsoleKey.Enter:
                    RenderDetail = true;
                    Console.Clear();
                    update = true;
                    break;
                }
            }
            T.Join();
            Console.Error.WriteLine("Exiting...");
            TorrentHandler.StopAll();
            foreach (var H in Handler.Where(m => m != null))
            {
                Console.Error.Write('.');
                H.SaveRecovery();
                H.Dispose();
            }
            TorrentHandler.SaveDhtNodes();
            Console.Error.WriteLine("DONE. Cleaning up...");
            return(RET.SUCCESS);
        }