private Task SetConfigAsync(InternalSessionInfo session, IMiraiSessionConfig config) { byte[] payload = JsonSerializer.SerializeToUtf8Bytes(new { sessionKey = session.SessionKey, cacheSize = config.CacheSize, enableWebsocket = config.EnableWebSocket }, JsonSerializeOptionsFactory.IgnoreNulls); return(InternalHttpPostAsync($"{session.Options.BaseUrl}/config", payload, session.Canceller.Token)); }
/// <inheritdoc/> public Task SetConfigAsync(IMiraiSessionConfig config, CancellationToken token = default) { InternalSessionInfo session = SafeGetSession(); if (session.ApiVersion.Major >= 2) { throw new NotSupportedException("自 mirai-api-http v2.0.0 起, 本接口不受支持"); } CreateLinkedUserSessionToken(session.Token, token, out CancellationTokenSource? cts, out token); return(SetConfigAsync(session, config, token).DisposeWhenCompleted(cts)); }
private Task SetConfigAsync(InternalSessionInfo session, IMiraiSessionConfig config, CancellationToken token = default) { var payload = new { sessionKey = session.SessionKey, cacheSize = config.CacheSize, enableWebsocket = config.EnableWebSocket }; return(_client.PostAsJsonAsync($"{_options.BaseUrl}/config", payload, JsonSerializeOptionsFactory.IgnoreNulls, session.Token).AsApiRespAsync(session.Token)); }
/// <summary> /// 异步连接到mirai-api-http。 /// </summary> /// <remarks> /// 此方法线程安全。但是在连接过程中, 如果尝试多次调用, 除了第一次以后的所有调用都将立即返回。 /// </remarks> /// <exception cref="BotNotFoundException"/> /// <exception cref="InvalidAuthKeyException"/> /// <param name="options">连接信息</param> /// <param name="qqNumber">Session将要绑定的Bot的qq号</param> /// <param name="listenCommand">是否监听指令相关的消息</param> public async Task ConnectAsync(MiraiHttpSessionOptions options, long qqNumber, bool listenCommand) { CheckDisposed(); InternalSessionInfo session = new InternalSessionInfo(); if (Interlocked.CompareExchange(ref SessionInfo, session, null !) == null) { try { session.Client = new HttpClient(); session.SessionKey = await AuthorizeAsync(session.Client, options); session.Options = options; await VerifyAsync(session.Client, options, session.SessionKey, qqNumber); session.QQNumber = qqNumber; session.ApiVersion = await GetVersionAsync(session.Client, options); CancellationTokenSource canceller = new CancellationTokenSource(); session.Canceller = canceller; session.Token = canceller.Token; session.Connected = true; IMiraiSessionConfig config = await this.GetConfigAsync(session); if (!config.EnableWebSocket.GetValueOrDefault()) { await this.SetConfigAsync(session, new MiraiSessionConfig { CacheSize = config.CacheSize, EnableWebSocket = true }); } CancellationToken token = session.Canceller.Token; ReceiveMessageLoop(session, token); if (listenCommand) { ReceiveCommandLoop(session, token); } } catch { Interlocked.CompareExchange(ref SessionInfo, null, session); _ = InternalReleaseAsync(session); throw; } } }
/// <summary> /// 异步连接到mirai-api-http。 /// </summary> /// <remarks> /// 此方法不是线程安全的。 /// </remarks> /// <exception cref="BotNotFoundException"/> /// <exception cref="InvalidAuthKeyException"/> /// <param name="options">连接信息</param> /// <param name="qqNumber">Session将要绑定的Bot的qq号</param> /// <param name="listenCommand">是否监听指令相关的消息</param> public async Task ConnectAsync(MiraiHttpSessionOptions options, long qqNumber, bool listenCommand) { CheckDisposed(); if (this.Connected) { return; } string sessionKey = await AuthorizeAsync(options); await VerifyAsync(options, sessionKey, qqNumber); ApiVersion = await GetVersionAsync(options); InternalSessionInfo session = new InternalSessionInfo { Options = options, SessionKey = sessionKey, QQNumber = qqNumber, Canceller = new CancellationTokenSource() }; try { IMiraiSessionConfig config = await this.GetConfigAsync(session); if (!config.EnableWebSocket.GetValueOrDefault()) { await this.SetConfigAsync(session, new MiraiSessionConfig { CacheSize = config.CacheSize, EnableWebSocket = true }); } CancellationToken token = session.Canceller.Token; ReceiveMessageLoop(session, token); if (listenCommand) { ReceiveCommandLoop(session, token); } SessionInfo = session; } catch // 如果这都报错那真是见了鬼了 { _ = InternalReleaseAsync(session); throw; } }
/// <summary> /// 异步设置当前Session的Config /// </summary> /// <param name="config">配置信息</param> public Task SetConfigAsync(IMiraiSessionConfig config) { CheckConnected(); return(SetConfigAsync(SessionInfo, config)); }
/// <inheritdoc/> public async Task ConnectAsync(long qqNumber, bool listenCommand, CancellationToken token = default) { CancellationTokenSource?instanceCts = Volatile.Read(ref _instanceCts); CancellationToken instanceToken = instanceCts?.Token ?? throw new ObjectDisposedException(this.GetType().Name); CancellationToken createdToken; InternalSessionInfo? previousSession = Volatile.Read(ref _currentSession); InternalSessionInfo? createdSession = null; if (previousSession != null || Interlocked.CompareExchange(ref _currentSession, createdSession = new InternalSessionInfo(instanceToken), null) != null) { createdSession?.Dispose(); throw new InvalidOperationException(); } createdToken = createdSession.Token; using CancellationTokenSource tempCts = CancellationTokenSource.CreateLinkedTokenSource(createdToken, token); CancellationToken tempToken = tempCts.Token; try { Version apiVersion = await GetVersionAsync(_client, _options, tempToken).ConfigureAwait(false); createdSession.ApiVersion = apiVersion; createdSession.QQNumber = qqNumber; createdSession.SessionKey = await AuthorizeAsync(_client, _options, apiVersion, tempToken).ConfigureAwait(false); await VerifyAsync(_client, _options, apiVersion, createdSession, tempToken).ConfigureAwait(false); bool v1 = apiVersion.Major < 2; if (v1) { IMiraiSessionConfig config = await this.GetConfigAsync(createdSession, tempToken).ConfigureAwait(false); if (!config.EnableWebSocket.GetValueOrDefault()) { await this.SetConfigAsync(createdSession, new MiraiSessionConfig { CacheSize = config.CacheSize, EnableWebSocket = true }, tempToken).ConfigureAwait(false); } } Task t1 = StartReceiveMessageLoopAsync(_options, createdSession, tempToken, createdToken); // mirai-api-http v2.0起, 指令ws合并进all, 所以只需连接上边这个就可以了 Task t2 = v1 && listenCommand?StartReceiveCommandLoopAsync(_options, createdSession, tempToken, createdToken) : Task.CompletedTask; await Task.WhenAll(t1, t2).ConfigureAwait(false); createdSession.Connected = true; } catch { if (Interlocked.CompareExchange(ref _currentSession, null !, createdSession) == createdSession) // 避免 StartReceiveMessageLoopAsync 和 // StartReceiveCommandLoopAsync 中间出现连接断开 // 导致释放两次 session { tempCts.Cancel(); createdSession.Dispose(); if (createdSession.SessionKey != null) { _ = InternalReleaseAsync(createdSession.SessionKey, qqNumber, instanceToken); } } throw; } }
/// <summary> /// 异步设置当前Session的Config /// </summary> /// <param name="config">配置信息</param> public Task SetConfigAsync(IMiraiSessionConfig config) { InternalSessionInfo session = SafeGetSession(); return(SetConfigAsync(session, config)); }