Cyrus-Vance_Magic-Conch/CyrusVance.CoolQRobot/Clients/Caller/ReverseWSCaller.cs
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using CyrusVance.CoolQRobot.ApiCall.Requests.Base;
using CyrusVance.CoolQRobot.ApiCall.Results.Base;
using CyrusVance.CoolQRobot.Clients.WebsocketUtils;
using CyrusVance.CoolQRobot.Utils;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace CyrusVance.CoolQRobot.Clients.Callers {
    class ReverseWSCaller : ICaller {
        WebsocketDaemon.WebsocketServerInstance server;
        object buffer_lock = new object ();
        Dictionary<long, JToken> buffer = new Dictionary<long, JToken> ();
        public ReverseWSCaller (
            int listen_port,
            string api_path,
            string access_token
        ) {
            api_path = api_path.Trim ('/');
            server = new WebsocketDaemon.WebsocketServerInstance (
                listen_port, api_path, access_token,
                m => {
                    Log.Debug ($"[reverse websocket received API response]:\n{m}");
                    JToken t = JToken.Parse (m);
                    lock (buffer_lock) {
                        buffer[t["echo"].ToObject<long> ()] = t;
                    }
                }
            );
        }
        public async Task<ApiResult> SendRequestAsync (ApiRequest request) {
            JObject constructor = new JObject ();
            long echo = DateTime.Now.ToBinary ();
            constructor["action"] = request.api_path.Substring (1);
            constructor["params"] = JObject.Parse (request.content);
            constructor["echo"] = echo;
            await server.socket.Send (constructor.ToString (Formatting.None));
            await new Func<bool> (
                () => buffer.ContainsKey (echo)
            ).TimeOut ("API调用超时");
            request.response.Parse (buffer[echo]);
            lock (buffer_lock) {
                buffer.Remove (echo);
            }
            return request.response;
        }
    }
}