public static string DecipherWithVersion(string cipher, string cipherVersion)
        {
            string jsUrl = string.Format("http://s.ytimg.com/yts/jsbin/player-{0}.js", cipherVersion);
            string js    = HttpHelper.DownloadString(jsUrl);

            //Find "C" in this: var A = B.sig||C (B.s)
            string functNamePattern = @"\""signature"",\s?([a-zA-Z0-9\$]+)\("; //Regex Formed To Find Word or DollarSign

            var funcName = Regex.Match(js, functNamePattern).Groups[1].Value;

            if (funcName.Contains("$"))
            {
                funcName = "\\" + funcName; //Due To Dollar Sign Introduction, Need To Escape
            }

            string funcPattern = @"(?!h\.)" + @funcName + @"=function\(\w+\)\{.*?\}";         //Escape funcName string
            var    funcBody    = Regex.Match(js, funcPattern, RegexOptions.Singleline).Value; //Entire sig function
            var    lines       = funcBody.Split(';');                                         //Each line in sig function

            string idReverse = "", idSlice = "", idCharSwap = "";                             //Hold name for each cipher method
            string functionIdentifier = "";
            string operations         = "";

            foreach (var line in lines.Skip(1).Take(lines.Length - 2)) //Matches the funcBody with each cipher method. Only runs till all three are defined.
            {
                if (!string.IsNullOrEmpty(idReverse) && !string.IsNullOrEmpty(idSlice) &&
                    !string.IsNullOrEmpty(idCharSwap))
                {
                    break; //Break loop if all three cipher methods are defined
                }

                functionIdentifier = GetFunctionFromLine(line);
                string reReverse = string.Format(@"{0}:\bfunction\b\(\w+\)", functionIdentifier);                        //Regex for reverse (one parameter)
                string reSlice   = string.Format(@"{0}:\bfunction\b\([a],b\).(\breturn\b)?.?\w+\.", functionIdentifier); //Regex for slice (return or not)
                string reSwap    = string.Format(@"{0}:\bfunction\b\(\w+\,\w\).\bvar\b.\bc=a\b", functionIdentifier);    //Regex for the char swap.

                if (Regex.Match(js, reReverse).Success)
                {
                    idReverse = functionIdentifier; //If def matched the regex for reverse then the current function is a defined as the reverse
                }

                if (Regex.Match(js, reSlice).Success)
                {
                    idSlice = functionIdentifier; //If def matched the regex for slice then the current function is defined as the slice.
                }

                if (Regex.Match(js, reSwap).Success)
                {
                    idCharSwap = functionIdentifier; //If def matched the regex for charSwap then the current function is defined as swap.
                }
            }

            foreach (var line in lines.Skip(1).Take(lines.Length - 2))
            {
                Match m;
                functionIdentifier = GetFunctionFromLine(line);

                if ((m = Regex.Match(line, @"\(\w+,(?<index>\d+)\)")).Success && functionIdentifier == idCharSwap)
                {
                    operations += "w" + m.Groups["index"].Value + " "; //operation is a swap (w)
                }

                if ((m = Regex.Match(line, @"\(\w+,(?<index>\d+)\)")).Success && functionIdentifier == idSlice)
                {
                    operations += "s" + m.Groups["index"].Value + " "; //operation is a slice
                }

                if (functionIdentifier == idReverse) //No regex required for reverse (reverse method has no parameters)
                {
                    operations += "r ";              //operation is a reverse
                }
            }

            operations = operations.Trim();

            return(DecipherWithOperations(cipher, operations));
        }
        public async static Task <string> DecipherWithVersion(string cipher, string cipherVersion)
        {
            // NB: We intentionally don't cache the operations as it seems that the same operation
            //     doesn't work if the URL below isn't called


            string jsUrl = string.Format("http://s.ytimg.com/yts/jsbin/html5player-{0}.js", cipherVersion);
            string js    = await HttpHelper.DownloadString(jsUrl);


            //Find "C" in this: var A = B.sig||C (B.s)
            string functNamePattern = @"\.sig\s*\|\|(\w+)\(";
            var    funcName         = Regex.Match(js, functNamePattern).Groups[1].Value;


            //Match nested angle braces
            string funcBodyPattern = @"(?<brace>{([^{}]| ?(brace))*})";
            //Match the function function_name (that has one argument)
            string funcPattern = string.Format(@"{0}\(\w+\){1}", funcName, funcBodyPattern);
            var    funcBody    = Regex.Match(js, funcPattern).Groups["brace"].Value;
            var    lines       = funcBody.Split(';');


            string operations = "";



            //CYNAO - 07/08/2014, Test Fix

            /* The previous algoritms used a.splice(), where the decipher used the method (.splice()), however it seems the new algoritm
             * renames the method to random but unique characters (example ab.dc() = splice). This code determines what each method code is,
             * as it is defined once using the original name.
             */
            string id_Reverse = "", id_Slice = "", id_CharSwap = ""; //Holds the new method name for each.
            string functionIdentifier = "";


            string functIDPattern = @"\w+:\bfunction\b";  //Define as "NB:function(a,b)" where nb can be the three ciphers
            var    funcID         = Regex.Match(js, functIDPattern).Groups[1].Value;


            ///CODE ADDITION: Get the three ciphers by finding the definition
            foreach (var line in lines.Skip(1).Take(lines.Length - 2))
            {
                string newVarName;                      //Previous algoritms used to be just "a." - now stores temp var name as its uneccessary
                int    locOfDot, locOfBracket, functionIDLength;
                locOfDot           = line.IndexOf("."); // NB.AC( - gets location of the dot.
                locOfBracket       = line.IndexOf("("); //NB.AC( - gets location of the bracet
                functionIDLength   = locOfBracket - (locOfDot + 1);
                newVarName         = line.Substring(0, locOfDot);
                functionIdentifier = line.Substring(locOfDot + 1, functionIDLength); //leaving us with the function AC


                //This is what the definitions currently look like, could be changed so the regex needs improving. Messy fix.
                string tempReverse  = string.Format(@"{0}:\bfunction\b\(\w+\)", functionIdentifier);                        //Reverse only one that doesnt have two parameters
                string tempSlice    = string.Format(@"{0}:\bfunction\b\([a],b\).(\breturn\b)?.?\w+\.", functionIdentifier); //Regex for slice (return or not)
                string tempCharSwap = string.Format(@"{0}:\bfunction\b\(\w+\,\w\).\bvar\b.\bc=a\b", functionIdentifier);    //Regex for the char swap.

                Match me;
                if ((me = Regex.Match(js, tempReverse)).Success)
                {
                    id_Reverse = functionIdentifier;
                }                                    //If def matched the regex for reverse then the current function is a defined as the reverse cipher


                if ((me = Regex.Match(js, tempSlice)).Success)
                {
                    id_Slice = functionIdentifier;
                }                                  //If def matched the regex for slice then the current function is defined as the slice cipher.


                if ((me = Regex.Match(js, tempCharSwap)).Success)
                {
                    id_CharSwap = functionIdentifier;
                }                                     //If def matched the regex for charSwap then the current function is defined as swap cipher.
            }



            foreach (var line in lines.Skip(1).Take(lines.Length - 2))
            {
                Match m;
                ///DUPLICATE CODE! Improve.
                int locOfDot; int locOfBracket; int functionIDLength;
                locOfDot           = line.IndexOf(".");
                locOfBracket       = line.IndexOf("(");
                functionIDLength   = locOfBracket - (locOfDot + 1);
                functionIdentifier = line.Substring(locOfDot + 1, functionIDLength); //Just needed this (define it as a member?)


                string newSliceIDRegex = string.Format(@"(?<index>\d+)\)+", functionIdentifier);


                if ((m = Regex.Match(line, @"\(\w+,(?<index>\d+)\)")).Success && functionIdentifier == id_CharSwap)
                {
                    operations += "w" + m.Groups["index"].Value + " ";
                }                                                      //Character swap regex appears to be the same as before



                if ((m = Regex.Match(line, @"\(\w+,(?<index>\d+)\)")).Success && functionIdentifier == id_Slice)
                {
                    operations += "s" + m.Groups["index"].Value + " ";
                }                                                      //Slice appears to have changed the index location???
                                                                       //Could be wrong and the regex needs improving, seems to work on the latest algorithm though.


                if (functionIdentifier == id_Reverse)
                {
                    operations += "r ";
                }                       //Reverse operation, no regex required
            }
            operations = operations.Trim();


            return(DecipherWithOperations(cipher, operations));
        }