/// <summary>
        /// 指定チャンネル、指定生放送のタイムシフトコメントを全取得
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        public bool GetChannelLiveComment(Channel channel, ChannelLiveInfo.Data item)
        {
            string dateString      = item.beginAt.ToString("yyyyMMdd");
            string defaultFileName = $"jk{channel.jk}_{dateString}.xml";
            string targetPath      = Param.GetOutputPath(channel.jk, defaultFileName);

            if (!OverWriteCheck(targetPath))
            {
                return(false);
            }

            if (!ExecuteGetter(out string tempFilePath, channel, item))
            {
                return(false);
            }

            if (!OverWriteCheck(targetPath))
            {
                return(false);
            }

            CheckTargetPath(targetPath);
            File.Move(tempFilePath, targetPath);

            Console.WriteLine(targetPath + " に出力しました");
            return(true);
        }
        /// <summary>
        /// 指定チャンネルのニコ生コメントをタイムシフトで取得する
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        public bool ExecuteGetter(out string tempFilePath, Channel channel, ChannelLiveInfo.Data item, bool isChase = false)
        {
            string getterExePath = JkTsGetter.Settings.Get().GetGetterToolPath();
            string tempFolder    = System.IO.Path.GetDirectoryName(getterExePath) + @"\rec";
            string tempFileName  = $"temp_lv{item.id}_0";

            tempFilePath = tempFolder + @"\" + tempFileName + ".xml";
            string cachePath = GetCacheFilePath(channel.jk, new DateTime(item.beginAt.Year, item.beginAt.Month, item.beginAt.Day));

            if (File.Exists(tempFilePath))
            {
                File.Delete(tempFilePath);
            }
            string getterParam = item.url + " -filenameformat=temp_{0} " + JkTsGetter.Settings.Get().Config.GetterToolParam;

            if (isChase)
            {
                getterParam += " " + JkTsGetter.Settings.Get().Config.GetterToolParamChase;
                Console.WriteLine($"{item.title} の追っかけ再生コメントを取得しています");
            }
            else
            {
                var liveInfo = Util.GetLiveProgramInfo(item.id);
                if (!liveInfo.data.timeshift.Gettable)
                {
                    Console.WriteLine($"{item.title} のタイムシフトコメントは取得できませんでした");
                    Console.WriteLine(liveInfo.data.timeshift.ErrorMessage);
                    return(false);
                }

                if (item.beginAt.Hour != 4 || item.endAt.Hour != 4)
                {
                    Console.WriteLine($"{item.title} ({item.beginAt.ToString("hh:mm")}-{item.endAt.ToString("hh:mm")}) のタイムシフトコメントを取得しています");
                }
                else
                {
                    Console.WriteLine($"{item.title} のタイムシフトコメントを取得しています");
                }
            }
            var process = System.Diagnostics.Process.Start(@getterExePath, getterParam);

            process.WaitForExit();

            if (JkTsGetter.Settings.Get().Config.UseSaveToCache&& !isChase)
            {
                if (cachePath.Contains(@"\"))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
                }

                if (!File.Exists(cachePath))
                {
                    Console.WriteLine($"キャッシュファイル {cachePath} を保存します");
                    File.Copy(tempFilePath, cachePath);
                }
            }

            return(File.Exists(tempFilePath));
        }
        /// <summary>
        /// 指定チャンネル、指定生放送のタイムシフトコメントをstringで全取得する
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        /// <summary>
        public string GetChannelLiveCommentXmlString(Channel channel, ChannelLiveInfo.Data item)
        {
            string xmlText = "";

            if (!ExecuteGetter(out string tempFilePath, channel, item))
            {
                return("");
            }

            StreamReader sr = new StreamReader(tempFilePath, Encoding.UTF8);

            xmlText = sr.ReadToEnd();
            sr.Close();

            return(xmlText);
        }
        /// <summary>
        /// 指定チャンネルのニコ生タイムシフトを追っかけ録画で取得する
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        public bool GetChannelLiveCommentChase(Channel channel, ChannelLiveInfo.Data item)
        {
            DateTime now             = DateTime.Now;
            string   dateString      = $"{item.beginAt.ToString("yyyyMMdd")}_{now.ToString("HHmmss")}";
            string   defaultFileName = $"jk{channel.jk}_{dateString}.xml";
            string   channelFolder   = $"\\jk{channel.jk}";
            string   targetPath      = Param.GetOutputPath(channel.jk, defaultFileName);

            if (!OverWriteCheck(targetPath))
            {
                return(false);
            }

            if (!ExecuteGetter(out string tempFilePath, channel, item, isChase: true))
            {
                return(false);
            }

            CheckTargetPath(targetPath);
            File.Move(tempFilePath, targetPath);

            Console.WriteLine(targetPath + " に出力しました");
            return(true);
        }
        /// <summary>
        /// 指定チャンネル、指定時間のログをstringで取得する 4時またぎ・時間分割非対応
        /// </summary>
        /// <param name="jk"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="liveData"></param>
        /// <returns></returns>
        public string GetLogXmlString(int jk, DateTime start, DateTime end, ChannelLiveInfo.Data liveData = null)
        {
            var channel = Channel.GetChannel(jk);

            string dateString      = start.ToString("yyyyMMddHHmmss") + "_" + end.ToString("yyyyMMddHHmmss");
            string defaultFileName = $"jk{channel.jk}_{dateString}.xml";

            string xmlText = "";

            if (start < NewJkBorderDateTime || Param.AlwaysOldApi)
            {
                xmlText = GetOldNicoJKLog(jk, start, end);
                return(xmlText);
            }

            DateTime getDate = start;

            if (getDate.Hour < 4)
            {
                getDate = getDate.AddDays(-1);
            }

            if (JkTsGetter.Settings.Get().Config.UseLoadFromCache)
            {
                string cachePath = GetCacheFilePath(channel.jk, new DateTime(getDate.Year, getDate.Month, getDate.Day));
                if (File.Exists(cachePath))
                {
                    Console.WriteLine($"キャッシュファイル {cachePath} から読み込みます");
                    StreamReader sre = new StreamReader(cachePath, Encoding.UTF8);
                    xmlText = sre.ReadToEnd();
                    sre.Close();
                    return(xmlText);
                }
            }

            bool done = false;
            // var item = Util.GetTimeShiftItem(channel, getDate.Year, getDate.Month, getDate.Day);
            var item = liveData;

            if (item != null)
            {
                var liveInfo = Util.GetLiveProgramInfo(item.id);
                if (liveInfo.data.timeshift.Gettable || liveInfo.data.timeshift.Status == LiveProgramInfo.TimeShift.StatusDef.BeforeRelease)
                {
                    // タイムシフト公開前は現在放送中 = 次の処理で追っかけ再生取得ができるとみなす
                    done = true;
                }
                else
                {
                    Console.WriteLine($"{item.title} のタイムシフトコメントは取得できませんでした");
                    Console.WriteLine(liveInfo.data.timeshift.ErrorMessage);
                }
            }
            else
            {
                // Console.WriteLine("この日のタイムシフトは見つかりませんでした");
            }

            if (!done)
            {
                // Console.WriteLine("かわりに過去ログAPIから取得してみます");

                xmlText = GetOldNicoJKLog(jk, start, end);
            }

            if (done)
            {
                done = false;
                string tempFilePath = "";

                switch (item.liveCycle)
                {
                case "ended":
                    done = ExecuteGetter(out tempFilePath, channel, item, isChase: false);
                    break;

                case "on_air":
                    done = ExecuteGetter(out tempFilePath, channel, item, isChase: true);
                    break;
                }

                StreamReader sr = new StreamReader(tempFilePath, Encoding.UTF8);
                xmlText = sr.ReadToEnd();
                sr.Close();

                File.Delete(tempFilePath);
            }

            if (!done)
            {
                return("");
            }

            DateTime getStart = new DateTime(getDate.Year, getDate.Month, getDate.Day, 4, 0, 0);
            DateTime getEnd   = getStart.AddDays(1);

            if (getStart < start || getEnd > end)
            {
                var xdoc = XDocument.Parse(xmlText);
                xdoc = TrimChatXmlFileTimeRange(xdoc, start, end);

                XmlWriterSettings settings = new XmlWriterSettings();
                settings.Indent      = true;
                settings.IndentChars = "";

                StringBuilder builder = new StringBuilder();
                using (XmlWriter writer = XmlTextWriter.Create(builder, settings))
                {
                    xdoc.Save(writer);
                }
                xmlText = builder.ToString();
            }

            return(xmlText);
        }