<|start_filename|>Traceless.SocketIO/Messages/IMessage.cs<|end_filename|>
﻿using Traceless.SocketIO.Helpers;
using System;
using System.Collections.Generic;
using System.Text;

namespace Traceless.SocketIO.Messages
{
    /// <summary>
    /// Interface for core Message class
    /// </summary>
    public interface IMessage
    {
        /// <summary>
        /// Enumeration of one of 9 basic messages provided by socket.io
        /// </summary>
        SocketIOMessageTypes MessageType { get; }

        /// <summary>
        /// <para>RawMessage includes the full socket.io message string</para>
        /// <para>[message type] ':' [message id ('+')] ':' [message endpoint] (':' [message data])</para>
        /// </summary>
        string RawMessage { get; }

        /// <summary>
        /// Event 'name' of originating message
        /// </summary>
        string Event { get; }

        /// <summary>
        /// AckId represents unique id associated with a message callback
        /// </summary>
        int? AckId { get; }

        /// <summary>
        /// Each socket is identified by an endpoint (can be omitted).
        /// </summary>
        string Endpoint { get; set; }

        /// <summary>
        /// String version of message data
        /// </summary>
        string MessageText { get; }

        JsonEncodedEventMessage Json { get; }

        [ObsoleteAttribute(".JsonEncodedMessage has been deprecated. Please use .Json instead.")]
        JsonEncodedEventMessage JsonEncodedMessage { get; }

        /// <summary>
        /// <para>
        /// Socket.IO encoded message structure - represents the actual message string sent to Socket.IO
        /// </para>
        /// <para>[message type] ':' [message id ('+')] ':' [message endpoint] (':' [message data])</para>
        /// </summary>
        string Encoded { get; }
    }
}

<|start_filename|>Traceless.SocketIO/Messages/Heartbeat.cs<|end_filename|>
﻿using Traceless.SocketIO.Helpers;
using System;
using System.Collections.Generic;
using System.Text;

namespace Traceless.SocketIO.Messages
{
    public class Heartbeat : Message
    {
        public static string HEARTBEAT = "2";

        public Heartbeat()
        {
            this.MessageType = SocketIOMessageTypes.Heartbeat;
        }

        public override string Encoded
        {
            get
            {
                return HEARTBEAT;
            }
        }
    }
}

<|start_filename|>Traceless.Utils/Ai/Tencent/Model/BaseRequest.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Traceless.Utils.Ai.Tencent.Model
{
    /// <summary>
    /// 请求公共参数
    /// </summary>
    public class BaseRequest
    {
        /// <summary>
        /// 【公共参数】应用标识（AppId）
        /// </summary>
        public int app_id { get; set; } = Apis.getAppId();

        /// <summary>
        /// 【公共参数】请求时间戳（秒级）
        /// </summary>
        public long time_stamp { get; set; } = TimeStamp.ConvertToTimeStamp(DateTime.Now) / 1000;

        /// <summary>
        /// 【公共参数】非空且长度上限32字节 随机字符串
        /// </summary>
        public string nonce_str { get; set; } = (TimeStamp.ConvertToTimeStamp(DateTime.Now) + "").Substring(0, 10);

        /// <summary>
        /// 【公共参数】非空且长度固定32字节 签名信息，详见接口鉴权
        /// </summary>
        public string sign { get; set; }
    }
}

<|start_filename|>Traceless.Utils/Ai/Tencent/Utils.cs<|end_filename|>
﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace Traceless.Utils.Ai.Tencent
{
    public class Utils
    {
        private const string rootUrl = @"https://api.ai.qq.com/";
        private const string aai_tts = @"fcgi-bin/aai/aai_tts";
        private const string textchat = @"fcgi-bin/nlp/nlp_textchat";
        private const string tex_smart = @"https://texsmart.qq.com/api";

        /// <summary>
        /// 获取语义分析
        /// </summary>
        /// <returns></returns>
        public static string getTexUrl()
        {
            return tex_smart;
        }

        /// <summary>
        /// 获取AI语音合成请求地址
        /// </summary>
        /// <returns></returns>
        public static string getAaiUrl()
        {
            return rootUrl + aai_tts;
        }

        /// <summary>
        /// 获取AI闲聊请求地址
        /// </summary>
        /// <returns></returns>
        public static string getChatUrl()
        {
            return rootUrl + textchat;
        }

        /// <summary>
        /// 获取腾讯AI签名
        /// </summary>
        /// <param name="appkey"></param>
        /// <param name="rawDic"></param>
        /// <returns></returns>
        public static string Sign(Dictionary<string, string> rawDic, string appkey, string charset = "utf-8")
        {
            var dic = rawDic.OrderBy(x => x.Key);
            var pair = "";
            foreach (var kv in dic)
            {
                if (!string.IsNullOrEmpty(kv.Value))
                {
                    pair += kv.Key + "=" + HttpUtils.UrlEncode(kv.Value, Encoding.GetEncoding(charset), true) + "&";
                }
            }
            pair += "app_key=" + appkey;
            var sign = HttpUtils.MD5(pair).ToUpper();
            return sign;
        }

        /// <summary>
        /// 获取腾讯AI签名
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        /// <param name="appkey"></param>
        /// <param name="charset"></param>
        /// <returns></returns>
        public static string Sign<T>(T model, string appkey, string charset = "utf-8") where T : class, new()
        {
            var m = model.GetType();
            var pis = m.GetProperties();
            var pair = new Dictionary<string, string>();
            foreach (var pi in pis)
            {
                if (pi.Name.ToLower() != "sign")
                {
                    object val = pi.GetValue(model, null);
                    pair.Add(pi.Name, val?.ToString() ?? "");
                }
            }

            var sign = Sign(pair, appkey, charset);

            return sign;
        }

        public static string Parameter<T>(T entity, string charset = "utf-8") where T : class, new()
        {
            string result = string.Empty;
            var pis = entity.GetType().GetProperties();
            foreach (var pi in pis)
            {
                string value = pi.GetValue(entity, null)?.ToString();
                if (value != null)
                {
                    result += "&" + pi.Name + "=" + value;
                }
            }
            return result.TrimStart('&');
        }

        /// <summary>
        /// 获取语义分析中的时间
        /// </summary>
        /// <param name="arr"></param>
        /// <returns></returns>
        public static DateTime parseTexDtArr(List<int> arr)
        {
            Console.WriteLine("[parseTexDtArr]" + JsonConvert.SerializeObject(arr));
            DateTime dt = DateTime.Now;
            switch (arr.Count)
            {
                case 1:

                    return new DateTime(arr[0], dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second);

                case 2:

                    return new DateTime(arr[0], arr[1], dt.Day, dt.Hour, dt.Minute, dt.Second);

                case 3:

                    return new DateTime(arr[0], arr[1], arr[2], 0, 0, 0);

                case 4:

                    return new DateTime(arr[0], arr[1], arr[2], arr[3], 0, 0);

                case 5:

                    return new DateTime(arr[0], arr[1], arr[2], arr[3], arr[4], 0);

                case 6:

                    return new DateTime(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5]);

                default:
                    return dt;
            }
        }
    }
}

<|start_filename|>Traceless.Utils/Http/TrHttpClientFactory.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Traceless.Utils.Http
{
    public class TrHttpClientFactory : TrHttpClientFactoryBase<ITrHttpClient, TrHttpClient>, ITrHttpClientFactory
    {
    }
}

<|start_filename|>Traceless.Utils/IniConfig/IniManager.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Traceless.Utils.IniConfig
{
    public class IniManager
    {
        private string _rootPath = "";
        private Dictionary<string, IniConfig> _dataDics = new Dictionary<string, IniConfig>();

        public IniManager(string rootPath)
        {
            _rootPath = rootPath;
        }

        /// <summary>
        /// 获取某个配置
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public IniConfig this[string key]
        {
            get
            {
                bool ok = _dataDics.TryGetValue(key, out IniConfig v);
                if (ok)
                {
                    return v;
                }
                return null;
            }
        }

        /// <summary>
        /// 增加配置
        /// </summary>
        /// <param name="iniName">文件名</param>
        /// <param name="iniConfig">配置文件</param>
        public void Add(string iniName, IniConfig iniConfig)
        {
            iniConfig.Save();
            _dataDics[iniName] = iniConfig;
        }

        /// <summary>
        /// 增加配置
        /// </summary>
        /// <param name="iniName"></param>
        /// <param name="func"></param>
        public void Add(string iniName, Func<IniConfig> func)
        {
            IniConfig iniConfig = func.Invoke();
            _dataDics[iniName] = iniConfig;
        }

        /// <summary>
        /// 获取某个配置
        /// </summary>
        /// <param name="iniName"></param>
        /// <returns></returns>
        public IniConfig Get(string iniName)
        {
            bool ok = _dataDics.TryGetValue(iniName, out IniConfig v);
            if (ok)
            {
                return v;
            }
            return null;
        }
    }
}

<|start_filename|>Traceless.Robot/Program.cs<|end_filename|>
﻿using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Traceless.OPQSDK.Models;
using Traceless.OPQSDK.Models.Event;
using Traceless.OPQSDK.Models.Msg;
using Traceless.Robot.Plugins;
using Traceless.SocketIO;
using Traceless.SocketIO.Messages;
using Traceless.Utils.Ai.Tencent;

namespace Traceless.Robot
{
    public class Program
    {
        private static async Task Main(string[] args)
        {
            Console.ReadLine();
            await OPQSDK.Plugin.OPQMain.Client();
            while (true)
            {
                string temp = Console.ReadLine();
            }
        }
    }
}

<|start_filename|>Traceless.SocketIO/Messages/EventMessage.cs<|end_filename|>
﻿using Traceless.SocketIO.Helpers;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Text.RegularExpressions;

namespace Traceless.SocketIO.Messages
{
    public class EventMessage : Message
    {
        private static object ackLock = new object();
        private static int _akid = 0;
        private string eventName;

        private static int NextAckID
        {
            get
            {
                lock (ackLock)
                {
                    _akid++;
                    if (_akid < 0)
                        _akid = 0;
                    return _akid;
                }
            }
        }

        public Action<dynamic> Callback;

        public EventMessage()
        {
            this.MessageType = SocketIOMessageTypes.Event;
        }

        public EventMessage(string eventName, string jsonObject, string endpoint = "", Action<dynamic> callBack = null)
            : this()
        {
            this.Callback = callBack;
            this.Endpoint = endpoint;
            this.eventName = eventName;

            if (callBack != null)
                this.AckId = EventMessage.NextAckID;

            //this.JsonEncodedMessage = new JsonEncodedEventMessage(eventName, jsonObject);
            this.MessageText = jsonObject;// this.Json.ToJsonString();
        }

        public static EventMessage Deserialize(string rawMessage)
        {
            EventMessage evtMsg = new EventMessage();
            evtMsg.RawMessage = rawMessage;
            try
            {
                string askId = rawMessage.Substring(2, rawMessage.IndexOf("[") - 2);
                int id;
                if (int.TryParse(askId, out id))
                    evtMsg.AckId = id;

                var groups = new Regex(@"\[([\s\S]*)\]", RegexOptions.IgnoreCase | RegexOptions.Compiled).Match(rawMessage).Groups;
                evtMsg.RawMessage = groups[0].Value.Replace("\\", "");
                //jsonMsg.Event = groups[1].Value;
                evtMsg.MessageText = groups[1].Value.Replace("\\", "").Trim('"');
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex);
            }
            return evtMsg;
        }

        public override string Encoded
        {
            get
            {
                //int msgId = (int)this.MessageType;
                if (this.AckId.HasValue)
                {
                    if (this.Callback == null)
                        //return string.Format("42{0}[\"{1}\",\"{2}\"]", this.AckId ?? -1, this.eventName, this.MessageText);
                        return string.Format("42{0}[\"{1}\",\"{2}\"]", this.AckId ?? -1, this.eventName, this.MessageText.Replace("\"", "\\\""));
                    else
                        return string.Format("42{0}[\"{1}\",\"{2}\"]", this.AckId ?? -1, this.eventName, this.MessageText.Replace("\"", "\\\""));
                }
                else
                    return string.Format("42[\"{0}\",\"{1}\"]", this.eventName, this.MessageText);
            }
        }
    }
}

<|start_filename|>Traceless.Utils/Music/Model/QQMusicResp.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Traceless.Utils.Music.Model
{
    public class QQMusicResp
    {
        public long code { get; set; }
        public Data data { get; set; }
        public string message { get; set; }

        public List<SongItem> getSongs()
        {
            if (data.song != null && data.song.list != null && data.song.list.Length > 0)
            {
                return data.song.list.ToList();
            }
            return new List<SongItem>();
        }
    }

    public class Data
    {
        public string keyword { get; set; }
        public Song song { get; set; }
    }

    public class Song
    {
        public long curnum { get; set; }
        public long curpage { get; set; }
        public SongItem[] list { get; set; }
        public long totalnum { get; set; }
    }

    public class SongItem
    {
        public Album album { get; set; }
        public string desc { get; set; }
        public string mid { get; set; }
        public string name { get; set; }
        public Singer[] singer { get; set; }
        public string time_public { get; set; }
        public string title { get; set; }
        public string title_hilight { get; set; }

        public string getJumpUrl()
        {
            return $"https://i.y.qq.com/v8/playsong.html?songtype=0&songmid={mid}";
        }

        public string getPreView()
        {
            return $"http://y.gtimg.cn/music/photo_new/T002R180x180M000{album.pmid}.jpg";
        }

        public string getSongUrl()
        {
            return $"http://aqqmusic.tc.qq.com/amobile.music.tc.qq.com/C400{mid}.m4a";
        }

        public string getDesc()
        {
            if (singer != null && singer.Length > 0)
            {
                return $"{name}-{string.Join("、", singer.Select(p => p.name).ToArray())}";
            }
            return title;
        }
    }

    public class Album
    {
        public long id { get; set; }
        public string mid { get; set; }
        public string name { get; set; }
        public string pmid { get; set; }
        public string subtitle { get; set; }
        public string title { get; set; }
        public string title_hilight { get; set; }
    }

    public class Singer
    {
        public long id { get; set; }
        public string mid { get; set; }
        public string name { get; set; }
        public string title { get; set; }
        public string title_hilight { get; set; }
        public long type { get; set; }
        public long uin { get; set; }
    }
}

<|start_filename|>Traceless.Utils/Http/TrHttpClient.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace Traceless.Utils.Http
{
    public class TrHttpClient : ITrHttpClient
    {
        private readonly IHttpClientFactory _clientFactory;

        public TrHttpClient(IHttpClientFactory clientFactory)
        {
            _clientFactory = clientFactory;
        }

        public Task<HttpResponseMessage> GetAsync(string url)
        {
            var request = new HttpRequestMessage(HttpMethod.Get,
                 new Uri(url));
            request.Headers.Clear();
            var client = _clientFactory.CreateClient();
            return client.SendAsync(request);
        }

        public Task<HttpResponseMessage> PostAsync(string url, string data, string contentType = "application/json")
        {
            var request = new HttpRequestMessage(HttpMethod.Post,
                new Uri(url));
            request.Headers.Clear();
            request.Content = new StringContent(data);
            request.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType);
            var client = _clientFactory.CreateClient();
            return client.SendAsync(request);
        }
    }
}

<|start_filename|>Traceless.Utils/Ai/Tencent/Model/Aai_TtsRequest.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Traceless.Utils.Ai.Tencent.Model
{
    /// <summary>
    /// 语音合成&gt;语音合成（AI Lab）
    /// </summary>
    public class Aai_TtsRequest : BaseRequest
    {
        /// <summary>
        /// 语音发音人编码，1-普通话男声 5-静琪女声 6-欢馨女声 7-碧萱女声
        /// </summary>
        public int speaker { get; set; } = 1;

        /// <summary>
        /// 合成语音格式编码，1-PCM 2-WAV 3-MP3
        /// </summary>
        public int format { get; set; } = 2;

        /// <summary>
        /// 合成语音音量，取值范围[-10, 10]，如-10表示音量相对默认值小10dB，0表示默认音量，10表示音量相对默认值大10dB
        /// </summary>
        public int volume { get; set; } = 0;

        /// <summary>
        /// 合成语音语速，取值范围[50, 200]，默认100
        /// </summary>
        public int speed { get; set; } = 100;

        /// <summary>
        /// UTF-8编码，非空且长度上限150字节
        /// </summary>
        public string text { get; set; }

        /// <summary>
        /// 合成语音降低/升高半音个数，即改变音高，默认0
        /// </summary>
        public int aht { get; set; } = 0;

        /// <summary>
        /// 控制频谱翘曲的程度，改变说话人的音色，取值范围[0, 100]，默认58
        /// </summary>
        public int apc { get; set; } = 58;
    }
}

<|start_filename|>Traceless.Utils/Ai/Tencent/Model/Nlp_TextChatResp.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Traceless.Utils.Ai.Tencent.Model
{
    /// <summary>
    /// 智能闲聊&gt;智能闲聊
    /// </summary>
    public class Nlp_TextChatResp
    {
        /// <summary>
        /// 会话标识（应用内唯一）,UTF-8编码，非空且长度上限32字节
        /// </summary>
        public string session { get; set; }

        /// <summary>
        /// 机器人返回数据
        /// </summary>
        public string answer { get; set; }
    }
}

<|start_filename|>Traceless.SocketIO/Messages/NoopMessage.cs<|end_filename|>
﻿using Traceless.SocketIO.Helpers;
using System;
using System.Collections.Generic;
using System.Text;

namespace Traceless.SocketIO.Messages
{
    public class NoopMessage : Message
    {
        public NoopMessage()
        {
            this.MessageType = SocketIOMessageTypes.Noop;
        }

        public static NoopMessage Deserialize(string rawMessage)
        {
            return new NoopMessage();
        }
    }
}

<|start_filename|>Traceless.Utils/Ai/Tencent/Model/Aai_TtsResp.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Traceless.Utils.Ai.Tencent.Model
{
    /// <summary>
    /// 语音合成&gt;优图
    /// </summary>
    public class Aai_TtsResp
    {
        /// <summary>
        /// pcm:1 wav:2 map:3
        /// </summary>
        public int format { get; set; }

        /// <summary>
        /// 合成语音的base64编码数据
        /// </summary>
        public string speech { get; set; }

        /// <summary>
        /// 合成语音的md5摘要（base64编码之前）
        /// </summary>
        public string md5sum { get; set; }
    }
}

<|start_filename|>Traceless.Utils/Ai/Tencent/Model/BaseResp.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Traceless.Utils.Ai.Tencent.Model
{
    public class BaseResp<T>
    {
        public int ret { get; set; }
        public string msg { get; set; }
        public T data { get; set; }
    }
}

<|start_filename|>Traceless.Utils/Ai/Tencent/Model/TexSmartResp.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;

namespace Traceless.Utils.Ai.Tencent.Model
{
    public class TexSmartResp
    {
        /// <summary>
        /// 调用执行后返回的辅助信息
        /// </summary>
        public Header header { get; set; }

        /// <summary>
        /// 输入句子正则化的结果
        /// </summary>
        public string norm_str { get; set; }

        public object lang { get; set; }

        /// <summary>
        /// 基础粒度分词和词性标注的结果
        /// </summary>
        public WordItemBase[] word_list { get; set; }

        /// <summary>
        /// 复合粒度分词和词性标注的结果
        /// </summary>
        public WordItemBase[] phrase_list { get; set; }

        /// <summary>
        /// 识别出的实体信息
        /// </summary>
        public EntityItem[] entity_list { get; set; }

        /// <summary>
        /// 成分句法分析的结果
        /// </summary>
        public string syntactic_parsing_str { get; set; }

        /// <summary>
        /// 语义角色标注的结果
        /// </summary>
        public string srl_str { get; set; }

        /// <summary>
        /// 获取语义中的时间
        /// </summary>
        public List<DateTime> FindTimes
        {
            get
            {
                return entity_list.Where(p => p.type.name.Contains("time.generic")).Select(p =>
                {
                    object[] valArr = p.meaning.value;
                    List<int> list = p.meaning.value.Where(p => long.TryParse(p.ToString(), out _)).Select(p => Convert.ToInt32(p.ToString())).ToList();
                    return Utils.parseTexDtArr(list);
                }).ToList();
            }
        }

        /// <summary>
        /// 获取wordList中语义为"CD"的分词并转化为数字
        /// </summary>
        public List<int> FindWordCd
        {
            get
            {
                return word_list.Where(p => p.tag == "CD").Select(p => (int)Chinese.ChineseNumber.GetNumber(p.str)).ToList();
            }
        }
    }

    public class Header
    {
        /// <summary>
        /// 处理请求所花的时间，以毫秒（ms）计算
        /// </summary>
        public float time_cost_ms { get; set; }

        /// <summary>
        /// 处理请求所花的时间，以秒来计算
        /// </summary>
        public float time_cost { get; set; }

        public float core_time_cost_ms { get; set; }

        /// <summary>
        /// 返回码，"succ"表示成功
        /// </summary>
        public string ret_code { get; set; }
    }

    public class WordItemBase
    {
        public string str { get; set; }
        public int[] hit { get; set; }
        public string tag { get; set; }
    }

    public class EntityItem : WordItemBase
    {
        public Type type { get; set; }
        public Meaning meaning { get; set; }
        public string tag_i18n { get; set; }
    }

    public class Type
    {
        public string name { get; set; }
        public string i18n { get; set; }
        public string path { get; set; }
    }

    public class Meaning
    {
        public object[] value { get; set; }
        public object[] related { get; set; }
    }
}

<|start_filename|>Traceless.SocketIO/MessageEventArgs.cs<|end_filename|>
﻿using Traceless.SocketIO.Messages;
using System;
using System.Collections.Generic;
using System.Text;

namespace Traceless.SocketIO
{
    public class MessageEventArgs : EventArgs
    {
        public IMessage Message { get; private set; }

        public MessageEventArgs(IMessage msg)
            : base()
        {
            this.Message = msg;
        }
    }
}

<|start_filename|>Traceless.Utils/Http/ITrHttpClientFactory.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Traceless.Utils.Http
{
    public interface ITrHttpClientFactory<IT, T> where T : class, IT where IT : class
    {
        IT CreateHttpClient();
    }

    public interface ITrHttpClientFactory : ITrHttpClientFactory<ITrHttpClient, TrHttpClient>
    {
    }
}

<|start_filename|>Traceless.SocketIO/Messages/JSONMessage.cs<|end_filename|>
﻿using Newtonsoft.Json;
using Traceless.SocketIO.Helpers;
using System;
using System.Collections.Generic;
using System.Text;

namespace Traceless.SocketIO.Messages
{
    public class JSONMessage : Message
    {
        public void SetMessage(object value)
        {
            this.MessageText = JsonConvert.SerializeObject(value, Formatting.None);
        }

        public virtual T Message<T>()
        {
            try { return JsonConvert.DeserializeObject<T>(this.MessageText); }
            catch (Exception ex)
            {
                // add error logging here
                throw;
            }
        }

        public JSONMessage()
        {
            this.MessageType = SocketIOMessageTypes.JSONMessage;
        }

        public JSONMessage(object jsonObject, int? ackId = null, string endpoint = null) : this()
        {
            this.AckId = ackId;
            this.Endpoint = endpoint;
            this.MessageText = JsonConvert.SerializeObject(jsonObject, Formatting.None);
        }

        public static JSONMessage Deserialize(string rawMessage)
        {
            JSONMessage jsonMsg = new JSONMessage();
            var groups = Messages.Message.ReMessageType.Match(rawMessage).Groups;
            jsonMsg.RawMessage = groups[0].Value;
            jsonMsg.Event = groups[1].Value;
            jsonMsg.MessageText = groups[2].Value;
            return jsonMsg;
        }
    }
}

<|start_filename|>Traceless.SocketIO/Helpers/SocketIOHandshake.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Traceless.SocketIO.Helpers
{
    public class SocketIOHandshake
    {
        public string SID { get; set; }
        public int HeartbeatTimeout { get; set; }
        public string ErrorMessage { get; set; }

        public bool HadError
        {
            get { return !string.IsNullOrWhiteSpace(this.ErrorMessage); }
        }

        /// <summary>
        /// The HearbeatInterval will be approxamately 20% faster than the Socket.IO service
        /// indicated was required
        /// </summary>
        public TimeSpan HeartbeatInterval
        {
            get
            {
                return new TimeSpan(0, 0, HeartbeatTimeout);
            }
        }

        public int ConnectionTimeout { get; set; }
        public List<string> Transports = new List<string>();

        public SocketIOHandshake()
        {
        }

        public static SocketIOHandshake LoadFromString(string value)
        {
            SocketIOHandshake returnItem = new SocketIOHandshake();

            if (!string.IsNullOrEmpty(value))
            {
                string[] items = value.Split(new char[] { ':' });
                if (items.Count() == 4)
                {
                    int hb = 0;
                    int ct = 0;
                    returnItem.SID = items[0];

                    if (int.TryParse(items[1], out hb))
                    {
                        var pct = (int)(hb * .75);  // setup client time to occure 25% faster than needed
                        returnItem.HeartbeatTimeout = pct;
                    }
                    if (int.TryParse(items[2], out ct))
                        returnItem.ConnectionTimeout = ct;
                    returnItem.Transports.AddRange(items[3].Split(new char[] { ',' }));
                    return returnItem;
                }
            }
            return null;
        }
    }
}

<|start_filename|>Traceless.Utils/Ai/Tencent/Model/TexSmartRequest.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Traceless.Utils.Ai.Tencent.Model
{
    public class TexSmartRequest
    {
        public string str { get; set; } = "";
    }
}

<|start_filename|>Traceless.Utils/Http/ITrHttpClient.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace Traceless.Utils.Http
{
    public interface ITrHttpClient
    {
        Task<HttpResponseMessage> PostAsync(string url, string data, string contentType = "application/json");

        Task<HttpResponseMessage> GetAsync(string url);
    }
}

<|start_filename|>Traceless.SocketIO/Client.cs<|end_filename|>
﻿using Traceless.SocketIO.Helpers;
using System.Threading;
using System.Threading.Tasks;
using System;
using System.Collections.Concurrent;
using Traceless.SocketIO.Messages;
using WebSocket4Net;
using System.Diagnostics;
using System.Net;

namespace Traceless.SocketIO
{
    public class Client : IDisposable, IClient
    {
        private Timer socketHeartBeatTimer; // HeartBeat timer
        private Task dequeuOutBoundMsgTask;
        private BlockingCollection<string> outboundQueue;
        private int retryConnectionCount = 0;
        private int retryConnectionAttempts = 3;
        private readonly static object padLock = new object(); // allow one connection attempt at a time

        /// <summary>
        /// Uri of Websocket server
        /// </summary>
        protected Uri uri;

        /// <summary>
        /// Underlying WebSocket implementation
        /// </summary>
        protected WebSocket wsClient;

        /// <summary>
        /// RegistrationManager for dynamic events
        /// </summary>
        protected RegistrationManager registrationManager;  // allow registration of dynamic events (event names) for client actions

        /// <summary>
        /// By Default, use WebSocketVersion.Rfc6455
        /// </summary>
        protected WebSocketVersion socketVersion = WebSocketVersion.Rfc6455;

        // Events
        /// <summary>
        /// Opened event comes from the underlying websocket client connection being opened. This is
        /// not the same as socket.io returning the 'connect' event
        /// </summary>
        public event EventHandler Opened;

        public event EventHandler<MessageEventArgs> Message;

        public event EventHandler ConnectionRetryAttempt;

        public event EventHandler HeartBeatTimerEvent;

        /// <summary>
        /// <para>The underlying websocket connection has closed (unexpectedly)</para>
        /// <para>
        /// The Socket.IO service may have closed the connection due to a heartbeat timeout, or the
        /// connection was just broken
        /// </para>
        /// <para>Call the client.Connect() method to re-establish the connection</para>
        /// </summary>
        public event EventHandler SocketConnectionClosed;

        public event EventHandler<ErrorEventArgs> Error;

        /// <summary>
        /// ResetEvent for Outbound MessageQueue Empty Event - all pending messages have been sent
        /// </summary>
        public ManualResetEvent MessageQueueEmptyEvent = new ManualResetEvent(true);

        /// <summary>
        /// Connection Open Event
        /// </summary>
        public ManualResetEvent ConnectionOpenEvent = new ManualResetEvent(false);

        /// <summary>
        /// Number of reconnection attempts before raising SocketConnectionClosed event - (default = 3)
        /// </summary>
        public int RetryConnectionAttempts
        {
            get { return this.retryConnectionAttempts; }
            set { this.retryConnectionAttempts = value; }
        }

        /// <summary>
        /// Value of the last error message text
        /// </summary>
        public string LastErrorMessage = "";

        /// <summary>
        /// Represents the initial handshake parameters received from the socket.io service (SID,
        /// HeartbeatTimeout etc)
        /// </summary>
        public SocketIOHandshake HandShake { get; private set; }

        /// <summary>
        /// Returns boolean of ReadyState == WebSocketState.Open
        /// </summary>
        public bool IsConnected
        {
            get
            {
                return this.ReadyState == WebSocketState.Open;
            }
        }

        /// <summary>
        /// Connection state of websocket client: None, Connecting, Open, Closing, Closed
        /// </summary>
        public WebSocketState ReadyState
        {
            get
            {
                if (this.wsClient != null)
                    return this.wsClient.State;
                else
                    return WebSocketState.None;
            }
        }

        // Constructors
        public Client(string url)
            : this(url, WebSocketVersion.Rfc6455)
        {
        }

        public Client(string url, WebSocketVersion socketVersion)
        {
            this.uri = new Uri(url);

            this.socketVersion = socketVersion;

            this.registrationManager = new RegistrationManager();
            this.outboundQueue = new BlockingCollection<string>(new ConcurrentQueue<string>());
            this.dequeuOutBoundMsgTask = Task.Factory.StartNew(() => dequeuOutboundMessages(), TaskCreationOptions.LongRunning);
        }

        /// <summary>
        /// Initiate the connection with Socket.IO service
        /// </summary>
        public void Connect()
        {
            lock (padLock)
            {
                if (!(this.ReadyState == WebSocketState.Connecting || this.ReadyState == WebSocketState.Open))
                {
                    try
                    {
                        this.ConnectionOpenEvent.Reset();
                        // this.HandShake = this.requestHandshake(uri);// perform an initial HTTP
                        // request as a new, non-handshaken connection

                        //if (this.HandShake == null || string.IsNullOrWhiteSpace(this.HandShake.SID) || this.HandShake.HadError)
                        if (this.HandShake != null)
                        {
                            this.LastErrorMessage = string.Format("Error initializing handshake with {0}", uri.ToString());
                            this.OnErrorEvent(this, new ErrorEventArgs(this.LastErrorMessage, new Exception()));
                        }
                        else
                        {
                            string wsScheme = (uri.Scheme == Uri.UriSchemeHttps ? "wss" : "ws");

                            var url = string.Format("{0}://{1}:{2}/socket.io/{3}", wsScheme, uri.Host, uri.Port, uri.Query);

                            this.wsClient = new WebSocket(
                                url,
                                string.Empty,
                                this.socketVersion);

                            this.wsClient.EnableAutoSendPing = true; // #4 tkiley: Websocket4net client library initiates a websocket heartbeat, causes delivery problems
                            this.wsClient.Opened += this.wsClient_OpenEvent;

                            this.wsClient.MessageReceived += this.wsClient_MessageReceived;
                            this.wsClient.Error += this.wsClient_Error;
                            //this.wsClient.Handshaked
                            this.wsClient.Closed += wsClient_Closed;

                            this.wsClient.Open();
                        }
                    }
                    catch (Exception ex)
                    {
                        Trace.WriteLine(string.Format("Connect threw an exception...{0}", ex.Message));
                        this.OnErrorEvent(this, new ErrorEventArgs("SocketIO.Client.Connect threw an exception", ex));
                    }
                }
            }
        }

        public IEndPointClient Connect(string endPoint)
        {
            EndPointClient nsClient = new EndPointClient(this, endPoint);
            this.Connect();
            this.Send(new ConnectMessage(endPoint));
            return nsClient;
        }

        protected void ReConnect()
        {
            this.retryConnectionCount++;

            this.OnConnectionRetryAttemptEvent(this, EventArgs.Empty);

            this.closeHeartBeatTimer(); // stop the heartbeat time
            this.closeWebSocketClient();// stop websocket

            this.Connect();

            bool connected = this.ConnectionOpenEvent.WaitOne(4000); // block while waiting for connection
            Trace.WriteLine(string.Format("\tRetry-Connection successful: {0}", connected));
            if (connected)
                this.retryConnectionCount = 0;
            else
            {   // we didn't connect - try again until exhausted
                if (this.retryConnectionCount < this.RetryConnectionAttempts)
                {
                    this.ReConnect();
                }
                else
                {
                    this.Close();
                    this.OnSocketConnectionClosedEvent(this, EventArgs.Empty);
                }
            }
        }

        /// <summary>
        /// <para>Asynchronously calls the action delegate on event message notification</para>
        /// <para>Mimicks the Socket.IO client 'socket.on('name',function(data){});' pattern</para>
        /// <para>
        /// Reserved socket.io event names available: connect, disconnect, open, close, error,
        /// retry, reconnect
        /// </para>
        /// </summary>
        /// <param name="eventName"></param>
        /// <param name="action"></param>
        /// <example>client.On("testme", (data) =&gt; { Debug.WriteLine(data.ToJson()); });</example>
        public virtual void On(
            string eventName,
            Action<IMessage> action)
        {
            this.registrationManager.AddOnEvent(eventName, action);
        }

        public virtual void On(
            string eventName,
            string endPoint,
            Action<IMessage> action)
        {
            this.registrationManager.AddOnEvent(eventName, endPoint, action);
        }

        /// <summary>
        /// <para>Asynchronously sends payload using eventName</para>
        /// <para>payload must a string or Json Serializable</para>
        /// <para>Mimicks Socket.IO client 'socket.emit('name',payload);' pattern</para>
        /// <para>
        /// Do not use the reserved socket.io event names: connect, disconnect, open, close, error,
        /// retry, reconnect
        /// </para>
        /// </summary>
        /// <param name="eventName"></param>
        /// <param name="payload">must be a string or a Json Serializable object</param>
        /// <remarks>ArgumentOutOfRangeException will be thrown on reserved event names</remarks>
        public void Emit(string eventName, dynamic payload, string endPoint = "", Action<dynamic> callback = null)
        {
            string lceventName = eventName.ToLower();
            IMessage msg = null;
            switch (lceventName)
            {
                case "message":
                    if (payload is string)
                        msg = new TextMessage() { MessageText = payload };
                    else
                        msg = new JSONMessage(payload);
                    this.Send(msg);
                    break;

                case "connect":
                case "disconnect":
                case "open":
                case "close":
                case "error":
                case "retry":
                case "reconnect":
                    Trace.WriteLine(string.Format("Emit ArgumentOutOfRangeException: {0}", msg.RawMessage));
                    throw new ArgumentOutOfRangeException(eventName, "Event name is reserved by socket.io, and cannot be used by clients or servers with this message type");
                default:
                    if (!string.IsNullOrWhiteSpace(endPoint) && !endPoint.StartsWith("/"))
                        endPoint = "/" + endPoint;
                    msg = new EventMessage(eventName, payload, endPoint, callback);
                    if (callback != null)
                        this.registrationManager.AddCallBack(msg);

                    this.Send(msg);
                    break;
            }
        }

        /// <summary>
        /// <para>Asynchronously sends payload using eventName</para>
        /// <para>payload must a string or Json Serializable</para>
        /// <para>Mimicks Socket.IO client 'socket.emit('name',payload);' pattern</para>
        /// <para>
        /// Do not use the reserved socket.io event names: connect, disconnect, open, close, error,
        /// retry, reconnect
        /// </para>
        /// </summary>
        /// <param name="eventName"></param>
        /// <param name="payload">must be a string or a Json Serializable object</param>
        public void Emit(string eventName, dynamic payload)
        {
            this.Emit(eventName, payload, string.Empty, null);
        }

        /// <summary>
        /// Queue outbound message
        /// </summary>
        /// <param name="msg"></param>
        public void Send(IMessage msg)
        {
            this.MessageQueueEmptyEvent.Reset();
            if (this.outboundQueue != null)
                this.outboundQueue.Add(msg.Encoded);
        }

        private void Send(string rawEncodedMessageText)
        {
            this.MessageQueueEmptyEvent.Reset();
            if (this.outboundQueue != null)
                this.outboundQueue.Add(rawEncodedMessageText);
        }

        /// <summary>
        /// if a registerd event name is found, don't raise the more generic Message event
        /// </summary>
        /// <param name="msg"></param>
        protected void OnMessageEvent(IMessage msg)
        {
            if (msg == null)
                return;

            bool skip = false;
            if (!string.IsNullOrEmpty(msg.Event) && registrationManager != null)
                skip = this.registrationManager.InvokeOnEvent(msg); //

            var handler = this.Message;
            if (handler != null && !skip)
            {
                Trace.WriteLine(string.Format("webSocket_OnMessage: {0}", msg.RawMessage));
                handler(this, new MessageEventArgs(msg));
            }
        }

        /// <summary>
        /// Close SocketIO4Net.Client and clear all event registrations
        /// </summary>
        public void Close()
        {
            this.retryConnectionCount = 0; // reset for next connection cycle
                                           // stop the heartbeat time
            this.closeHeartBeatTimer();

            // stop outbound messages
            this.closeOutboundQueue();

            this.closeWebSocketClient();

            if (this.registrationManager != null)
            {
                this.registrationManager.Dispose();
                this.registrationManager = null;
            }
        }

        protected void closeHeartBeatTimer()
        {
            // stop the heartbeat timer
            if (this.socketHeartBeatTimer != null)
            {
                this.socketHeartBeatTimer.Change(Timeout.Infinite, Timeout.Infinite);
                this.socketHeartBeatTimer.Dispose();
                this.socketHeartBeatTimer = null;
            }
        }

        protected void closeOutboundQueue()
        {
            // stop outbound messages
            if (this.outboundQueue != null)
            {
                this.outboundQueue.CompleteAdding(); // stop adding any more items;
                this.dequeuOutBoundMsgTask.Wait(700); // wait for dequeue thread to stop
                this.outboundQueue.Dispose();
                this.outboundQueue = null;
            }
        }

        protected void closeWebSocketClient()
        {
            if (this.wsClient != null)
            {
                // unwire events
                this.wsClient.Closed -= this.wsClient_Closed;
                this.wsClient.MessageReceived -= wsClient_MessageReceived;
                this.wsClient.Error -= wsClient_Error;
                this.wsClient.Opened -= this.wsClient_OpenEvent;

                if (this.wsClient.State == WebSocketState.Connecting || this.wsClient.State == WebSocketState.Open)
                {
                    try { this.wsClient.Close(); }
                    catch { Trace.WriteLine("exception raised trying to close websocket: can safely ignore, socket is being closed"); }
                }
                this.wsClient = null;
            }
        }

        // websocket client events - open, messages, errors, closing
        private void wsClient_OpenEvent(object sender, EventArgs e)
        {
            //30秒心跳
            // this.socketHeartBeatTimer = new Timer(OnHeartBeatTimerCallback, new object(), HandShake.HeartbeatInterval, HandShake.HeartbeatInterval);
            this.socketHeartBeatTimer = new Timer(OnHeartBeatTimerCallback, new object(), 30000, 30000);

            this.ConnectionOpenEvent.Set();

            this.OnMessageEvent(new EventMessage() { Event = "open" });
            if (this.Opened != null)
            {
                try { this.Opened(this, EventArgs.Empty); }
                catch (Exception ex) { Trace.WriteLine(ex); }
            }
        }

        /// <summary>
        /// Raw websocket messages from server - convert to message types and call subscribers of
        /// events and/or callbacks
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void wsClient_MessageReceived(object sender, MessageReceivedEventArgs e)
        {
            IMessage iMsg = Messages.Message.Factory(e.Message);
            //Trace.WriteLine(string.Format("InvokeOnEvent: {0}", iMsg.MessageText));
            if (iMsg.Event == "responseMsg")
                Trace.WriteLine(string.Format("InvokeOnEvent: {0}", iMsg.RawMessage));

            switch (iMsg.MessageType)
            {
                case SocketIOMessageTypes.Disconnect:
                    this.OnMessageEvent(iMsg);
                    if (string.IsNullOrWhiteSpace(iMsg.Endpoint)) // Disconnect the whole socket
                        this.Close();
                    break;

                case SocketIOMessageTypes.Heartbeat:
                    this.OnHeartBeatTimerCallback(null);
                    break;

                case SocketIOMessageTypes.Connect:
                case SocketIOMessageTypes.Message:
                case SocketIOMessageTypes.JSONMessage:
                case SocketIOMessageTypes.Event:
                case SocketIOMessageTypes.Error:
                    this.OnMessageEvent(iMsg);
                    break;

                case SocketIOMessageTypes.ACK:
                    this.registrationManager.InvokeCallBack(iMsg.AckId, iMsg.RawMessage);
                    break;

                default:
                    Trace.WriteLine("unknown wsClient message Received... " + e.Message);
                    break;
            }
        }

        /// <summary>
        /// websocket has closed unexpectedly - retry connection
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void wsClient_Closed(object sender, EventArgs e)
        {
            if (this.retryConnectionCount < this.RetryConnectionAttempts)
            {
                this.ConnectionOpenEvent.Reset();
                this.ReConnect();
            }
            else
            {
                this.Close();
                this.OnSocketConnectionClosedEvent(this, EventArgs.Empty);
            }
        }

        private void wsClient_Error(object sender, SuperSocket.ClientEngine.ErrorEventArgs e)
        {
            this.OnErrorEvent(sender, new ErrorEventArgs("SocketClient error", e.Exception));
        }

        protected void OnErrorEvent(object sender, ErrorEventArgs e)
        {
            this.LastErrorMessage = e.Message;
            if (this.Error != null)
            {
                try { this.Error.Invoke(this, e); }
                catch { }
            }
            Trace.WriteLine(string.Format("Error Event: {0}\r\n\t{1}", e.Message, e.Exception));
        }

        protected void OnSocketConnectionClosedEvent(object sender, EventArgs e)
        {
            if (this.SocketConnectionClosed != null)
            {
                try { this.SocketConnectionClosed(sender, e); }
                catch { }
            }
            Trace.WriteLine("SocketConnectionClosedEvent");
        }

        protected void OnConnectionRetryAttemptEvent(object sender, EventArgs e)
        {
            if (this.ConnectionRetryAttempt != null)
            {
                try { this.ConnectionRetryAttempt(sender, e); }
                catch (Exception ex) { Trace.WriteLine(ex); }
            }
            Trace.WriteLine(string.Format("Attempting to reconnect: {0}", this.retryConnectionCount));
        }

        // Housekeeping
        protected void OnHeartBeatTimerCallback(object state)
        {
            if (this.ReadyState == WebSocketState.Open)
            {
                IMessage msg = new Heartbeat();
                try
                {
                    if (this.outboundQueue != null && !this.outboundQueue.IsAddingCompleted)
                    {
                        this.outboundQueue.Add(msg.Encoded);
                        if (this.HeartBeatTimerEvent != null)
                        {
                            Task.Run(() => this.HeartBeatTimerEvent.Invoke(this, EventArgs.Empty));
                        }
                    }
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(string.Format("OnHeartBeatTimerCallback Error Event: {0}\r\n\t{1}", ex.Message, ex.InnerException));
                }
            }
        }

        private void EndAsyncEvent(IAsyncResult result)
        {
            Trace.WriteLine("result");
            //var ar = (System.Runtime.Remoting.Messaging.AsyncResult)result;
            //var invokedMethod = (EventHandler)ar.AsyncDelegate;
            //var invokedMethod = (EventHandler)result.AsyncDelegate;
            //try
            //{
            //    invokedMethod.EndInvoke(result);
            //}
            //catch
            //{
            //    // Handle any exceptions that were thrown by the invoked method
            //    Trace.WriteLine("An event listener went kaboom!");
            //}
        }

        /// <summary>
        /// While connection is open, dequeue and send messages to the socket server
        /// </summary>
        protected void dequeuOutboundMessages()
        {
            while (this.outboundQueue != null && !this.outboundQueue.IsAddingCompleted)
            {
                if (this.ReadyState == WebSocketState.Open)
                {
                    string msgString;
                    try
                    {
                        if (this.outboundQueue.TryTake(out msgString, 500))
                        {
                            //Trace.WriteLine(string.Format("webSocket_Send: {0}", msgString));
                            this.wsClient.Send(msgString);
                        }
                        else
                            this.MessageQueueEmptyEvent.Set();
                    }
                    catch (Exception ex)
                    {
                        Trace.WriteLine("The outboundQueue is no longer open...");
                    }
                }
                else
                {
                    this.ConnectionOpenEvent.WaitOne(2000); // wait for connection event
                }
            }
        }

        /// <summary>
        /// <para>
        /// Client performs an initial HTTP POST to obtain a SessionId (sid) assigned to a client,
        /// followed by the heartbeat timeout, connection closing timeout, and the list of supported transports.
        /// </para>
        /// <para>The tansport and sid are required as part of the ws: transport connection</para>
        /// </summary>
        /// <param name="uri">http://localhost:3000</param>
        /// <returns>Handshake object with sid value</returns>
        /// <example>DownloadString: 13052140081337757257:15:25:websocket,htmlfile,xhr-polling,jsonp-polling</example>
        protected SocketIOHandshake requestHandshake(Uri uri)
        {
            string value = string.Empty;
            string errorText = string.Empty;
            SocketIOHandshake handshake = null;

            using (WebClient client = new WebClient())
            {
                try

                {
                    var url = string.Format("{0}://{1}:{2}/socket.io/{3}", uri.Scheme, uri.Host, uri.Port, uri.Query);
                    client.Headers.Add("Upgrade", "websocket");
                    client.Headers.Add("Connection", "Upgrade");
                    client.Headers.Add("Sec-Websocket-Version", "13");
                    client.Headers.Add("Sec-WebSocket-Key", "<KEY>);
                    value = client.DownloadString(url); // #5 tkiley: The uri.Query is available in socket.io's handshakeData object during authorization
                    //value = client.ResponseHeaders.Get("Sec-WebSocket-Accept");                                // 13052140081337757257:15:25:websocket,htmlfile,xhr-polling,jsonp-polling
                    if (string.IsNullOrEmpty(value))
                        errorText = "Did not receive handshake string from server";
                }
                catch (Exception ex)
                {
                    errorText = string.Format("Error getting handsake from Socket.IO host instance: {0}", ex.Message);
                    //this.OnErrorEvent(this, new ErrorEventArgs(errMsg));
                }
            }
            if (string.IsNullOrEmpty(errorText))
                handshake = SocketIOHandshake.LoadFromString(value);
            else
            {
                handshake = new SocketIOHandshake();
                handshake.ErrorMessage = errorText;
            }

            return handshake;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        // The bulk of the clean-up code
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                // free managed resources
                this.Close();
                this.MessageQueueEmptyEvent.Dispose();
                this.ConnectionOpenEvent.Dispose();
            }
        }
    }
}

<|start_filename|>Traceless.SocketIO/IEndPointClient.cs<|end_filename|>
﻿using Traceless.SocketIO.Messages;
using System;
using System.Collections.Generic;
using System.Text;

namespace Traceless.SocketIO
{
    public interface IEndPointClient
    {
        void On(string eventName, Action<IMessage> action);

        void Emit(string eventName, dynamic payload, Action<dynamic> callBack = null);

        void Send(IMessage msg);
    }
}

<|start_filename|>Traceless.Utils/TimeStamp.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Traceless.Utils
{
    public class TimeStamp
    {
        /// <summary>
        /// 日期转换为时间戳（时间戳单位ms）
        /// </summary>
        /// <param name="TimeStamp"></param>
        /// <returns></returns>
        public static long ConvertToTimeStamp(DateTime time)
        {
            DateTime Jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            return (long)(time.AddHours(-8) - Jan1st1970).TotalMilliseconds;
        }
    }
}

<|start_filename|>Traceless.OPQSDK/Models/Msg/OPQCode.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace Traceless.OPQSDK.Models.Msg
{
    public class OPQCode
    {
        #region --字段--

        private static readonly Lazy<Regex[]> _regices = new Lazy<Regex[]>(InitializeRegex);

        private string _originalString;
        private OPQFunction _type;
        private bool _convert = true;
        private Dictionary<string, string> _items;

        #endregion --字段--

        #region --属性--

        /// <summary>
        /// 获取一个值, 指示当前实例的功能
        /// </summary>
        public OPQFunction Function { get { return _type; } }

        /// <summary>
        /// 获取当前实例所包含的所有项目
        /// </summary>
        public Dictionary<string, string> Items { get { return _items; } }

        /// <summary>
        /// 获取一个值, 指示当前实例是否属于图片 <see cref="OPQCode"/>
        /// </summary>
        public bool IsImageOPQCode { get { return EqualIsImageOPQCode(this); } }

        #endregion --属性--

        #region --构造函数--

        /// <summary>
        /// 使用 OPQ码 字符串初始化 <see cref="OPQCode"/> 类的新实例
        /// </summary>
        /// <param name="str">OPQ码字符串 或 包含OPQ码的字符串</param>
        private OPQCode(string str)
        {
            this._originalString = str;

            #region --解析 OPQCode--

            Match match = _regices.Value[0].Match(str);
            if (!match.Success)
            {
                throw new FormatException("无法解析所传入的字符串, 字符串非OPQ码格式!");
            }

            #endregion --解析 OPQCode--

            #region --解析OPQ码类型--

            if (!System.Enum.TryParse<OPQFunction>(match.Groups[1].Value, true, out _type))
            {
                this._type = OPQFunction.Unknown;    // 解析不出来的时候, 直接给一个默认
            }

            #endregion --解析OPQ码类型--

            #region --解析键值对--

            MatchCollection collection = _regices.Value[1].Matches(match.Groups[2].Value);
            this._items = new Dictionary<string, string>(collection.Count);
            foreach (Match item in collection)
            {
                this._items.Add(item.Groups[1].Value, OPQDeCode(item.Groups[2].Value));
            }

            #endregion --解析键值对--
        }

        public static string OPQDeCode(string source)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            StringBuilder builder = new StringBuilder(source);
            builder = builder.Replace("&#91;", "[");
            builder = builder.Replace("&#93;", "]");
            builder = builder.Replace("&#44;", ",");
            builder = builder.Replace("&amp;", "&");
            return builder.ToString();
        }

        /// <summary>
        /// 初始化 <see cref="OPQCode"/> 类的新实例
        /// </summary>
        /// <param name="type">OPQ码类型</param>
        /// <param name="keyValues">包含的键值对</param>
        public OPQCode(OPQFunction type, params KeyValuePair<string, string>[] keyValues)
        {
            this._type = type;
            this._items = new Dictionary<string, string>(keyValues.Length);
            foreach (KeyValuePair<string, string> item in keyValues)
            {
                this._items.Add(item.Key, item.Value);
            }

            this._originalString = null;
        }

        #endregion --构造函数--

        #region --公开方法--

        /// <summary>
        /// 从字符串中解析出所有的 OPQ码, 转换为 <see cref="OPQCode"/> 集合
        /// </summary>
        /// <param name="source">原始字符串</param>
        /// <returns>返回等效的 <see cref="List{OPQCode}"/></returns>
        public static List<OPQCode> Parse(string source)
        {
            MatchCollection collection = _regices.Value[0].Matches(source);
            List<OPQCode> codes = new List<OPQCode>(collection.Count);
            foreach (Match item in collection)
            {
                codes.Add(new OPQCode(item.Groups[0].Value));
            }
            return codes;
        }

        /// <summary>
        /// 判断是否是图片 <see cref="OPQCode"/>
        /// </summary>
        /// <param name="code">要判断的 <see cref="OPQCode"/> 实例</param>
        /// <returns>如果是图片 <see cref="OPQCode"/> 返回 <see langword="true"/> 否则返回 <see langword="false"/></returns>
        public static bool EqualIsImageOPQCode(OPQCode code)
        {
            return code.Function == OPQFunction.Pic;
        }

        /// <summary>
        /// 确定指定的对象是否等于当前对象
        /// </summary>
        /// <param name="obj">要与当前对象进行比较的对象</param>
        /// <returns>
        /// 如果指定的对象等于当前对象，则为
        /// <code>true</code>
        /// ，否则为
        /// <code>false</code>
        /// </returns>
        public override bool Equals(object obj)
        {
            OPQCode code = obj as OPQCode;
            if (code != null)
            {
                return string.Equals(this._originalString, code._originalString);
            }
            return base.Equals(obj);
        }

        /// <summary>
        /// 返回该字符串的哈希代码
        /// </summary>
        /// <returns>32 位有符号整数哈希代码</returns>
        public override int GetHashCode()
        {
            return base.GetHashCode() & this._originalString.GetHashCode();
        }

        /// <summary>
        /// 返回此实例等效的OPQ码形式
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            if (this._originalString == null)
            {
                if (this._items.Count == 0)
                {
                    return "";
                }
                else
                {
                    // 普通OPQ码, 带参数
                    StringBuilder builder = new StringBuilder();
                    builder.Append("[CODE:");
                    builder.Append(this._type.GetDescription());   // function
                    foreach (KeyValuePair<string, string> item in this._items)
                    {
                        builder.AppendFormat(",{0}={1}", item.Key, OPQEnCode(item.Value, true));
                    }
                    builder.Append("]");
                    this._originalString = builder.ToString();
                }
            }
            return this._originalString;
        }

        public static string OPQEnCode(string source, bool enCodeComma)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            StringBuilder builder = new StringBuilder(source);
            builder = builder.Replace("&", "&amp;");
            builder = builder.Replace("[", "&#91;");
            builder = builder.Replace("]", "&#93;");
            if (enCodeComma)
            {
                builder = builder.Replace(",", "&#44;");
            }
            return builder.ToString();
        }

        #endregion --公开方法--

        #region --私有方法--

        /// <summary>
        /// 延时初始化正则表达式
        /// </summary>
        /// <returns></returns>
        private static Regex[] InitializeRegex()
        {
            // 此处延时加载, 以提升运行速度
            return new Regex[]
            {
                new Regex(@"\[CODE:([A-Za-z]*)(?:(,[^\[\]]+))?\]", RegexOptions.Compiled),    // 匹配OPQ码
                new Regex(@",([A-Za-z]+)=([^,\[\]]+)", RegexOptions.Compiled)               // 匹配键值对
            };
        }

        #endregion --私有方法--
    }
}

<|start_filename|>Traceless.Utils/IniConfig/Attribute/IniConfigKeyAttribute.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Traceless.Utils.IniConfig.Attribute
{
    /// <summary>
    /// 表示 IniConfig 在序列化时将表示为键的特性
    /// </summary>
    [Obsolete("该类型跟随 IniConvert 类型过期")]
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
    public sealed class IniConfigKeyAttribute : System.Attribute
    {
        /// <summary>
        /// 表示 IniConfig 文件中存储的键名称
        /// </summary>
        public string KeyName { get; set; }

        /// <summary>
        /// 初始化 <see cref="IniConfigKeyAttribute"/> 类的新实例
        /// </summary>
        public IniConfigKeyAttribute()
            : this(null)
        { }

        /// <summary>
        /// 初始化 <see cref="IniConfigKeyAttribute"/> 类的新实例
        /// </summary>
        /// <param name="keyName">用于表示键值对 "键" 的名称</param>
        public IniConfigKeyAttribute(string keyName)
        {
            this.KeyName = keyName;
        }
    }
}