private void AddComment(CommentRecord comment)
 {
     this.Dispatcher.Invoke(() =>
     {
         int where = 0;
         if (comment.CreatedAt == null || comment.CreatedAt.Ticks == 0)
         {
             comment.CreatedAt = new DateTime(DateTime.Now.Ticks);
         }
         else
         {
             foreach (var c in this.Comments)
             {
                 if (comment.CreatedAt < c.CreatedAt)
                 {
                     where++;
                 }
             }
         }
         this.Comments.Insert(where, comment);
         if (where == 0)
         {
             bouyomichan.say(comment.Content);
         }
     });
 }
        public async void MastodonConnect(string serviceName, string serviceType, string httpApi, string websocketApi)
        {
            // 過去ログ取得
            using (var client = new HttpClient())
            {
                var result = await client.GetAsync(httpApi);

                Console.WriteLine(result.ToString());
                if (!result.IsSuccessStatusCode)
                {
                    this.AddComment(new CommentRecord
                    {
                        Type     = "Sys",
                        UserName = "******",
                        Content  = serviceName + "からの過去ログ取得に失敗(HTTP_STATUS=" + result.StatusCode + ")",
                    });
                    this.ChangeConnectionState(ConnectionStateEnum.NotConnected);
                    return;
                }
                using (var stream = await result.Content.ReadAsStreamAsync())
                {
                    var serializer = new DataContractJsonSerializer(typeof(MastodonStatus[]));
                    var statuses   = (MastodonStatus[])serializer.ReadObject(stream);
                    foreach (var status in statuses)
                    {
                        var record = new CommentRecord
                        {
                            Type      = serviceType,
                            UserName  = status.Account.Name,
                            Content   = Regex.Replace(status.Content, "<.+?>", "").Replace("#" + this.liveInfo.Hashtag, ""),
                            CreatedAt = DateTime.Parse(status.CreatedAt),
                        };
                        if (status.CreatedAt != null)
                        {
                            record.CreatedAt = DateTime.Parse(status.CreatedAt);
                        }
                        else
                        {
                            record.CreatedAt = new DateTime(0);
                        }
                        this.AddComment(record);
                    }
                    this.AddComment(new CommentRecord
                    {
                        Type     = "Sys",
                        UserName = "******",
                        Content  = serviceName + "から過去ログを取得しました",
                    });
                }
            }

            var ws = new WebSocket(websocketApi);

            ws.SslConfiguration.EnabledSslProtocols = System.Security.Authentication.SslProtocols.Tls12;

            ws.OnOpen += (_s, _e) =>
            {
                this.AddComment(new CommentRecord {
                    Type     = "Sys",
                    UserName = "******",
                    Content  = serviceName + "のストリームに接続しました",
                });
                this.ChangeConnectionState(ConnectionStateEnum.Connected);

                var pingTimer = new Timer(10 * 1000);
                pingTimer.Elapsed += (__s, __e) =>
                {
                    Console.WriteLine("send ping");
                    ws.Send("ping");
                };
                pingTimer.AutoReset = true;
                pingTimer.Enabled   = true;
            };

            ws.OnMessage += (_s, _e) =>
            {
                Console.WriteLine("event" + _e.Data);
                var dataStream = new MemoryStream(Encoding.UTF8.GetBytes(_e.Data));
                var eventContainerSerializer = new DataContractJsonSerializer(typeof(MastodonStreamingEvent));
                var streamEvent = (MastodonStreamingEvent)eventContainerSerializer.ReadObject(dataStream);
                if (streamEvent.EventType != "update")
                {
                    if (streamEvent.EventType != "pong")
                    {
                        Console.WriteLine("eventtype is not update: " + streamEvent.EventType);
                    }
                    return;
                }
                dataStream.Close();
                dataStream = new MemoryStream(Encoding.UTF8.GetBytes(streamEvent.Payload));
                var statusSerializer = new DataContractJsonSerializer(typeof(MastodonStatus));
                var status           = (MastodonStatus)statusSerializer.ReadObject(dataStream);
                var record           = new CommentRecord
                {
                    Type     = serviceType,
                    UserName = status.Account.Name,
                    Content  = Regex.Replace(status.Content, "<.+?>", "").Replace("#" + this.liveInfo.Hashtag, ""),
                };
                if (status.CreatedAt != null)
                {
                    record.CreatedAt = DateTime.Parse(status.CreatedAt);
                }
                this.AddComment(record);
            };
            ws.Connect();
        }