├── .editorconfig ├── .gitattributes ├── .gitignore ├── Directory.Build.props ├── Executorlibs.sln ├── LICENSE ├── README.md └── src ├── Executorlibs.AspNetCore.Identity ├── ClaimLoadingOptions.cs ├── Executorlibs.AspNetCore.Identity.csproj ├── IRoleStore.cs ├── IUserStore.cs ├── IdentityDbContextAttribute.cs ├── IdentityRoleStoreProvider.cs ├── IdentityStoreResolver.cs ├── IdentityStoreServiceExtensions.cs ├── IdentityUserStoreProvider.cs ├── ManagerResolver.cs ├── RoleClaimsLoadingOptions.cs ├── RoleManager.cs ├── RoleStoreProxy.cs ├── SignInManager.cs ├── TypeResolver.cs ├── UserClaimsPrincipalFactory.cs ├── UserClaimsPrincipalFactoryProvider.cs ├── UserClaimsPrincipalFactoryResolver.cs ├── UserClaimsPrincipalLoader.cs ├── UserManager.cs ├── UserOnlyStoreProxy.cs └── UserStoreProxy.cs ├── Executorlibs.AspNetCore.Mvc ├── ApplicationModels │ ├── SubAreaApplicationModelProvider.cs │ ├── SubComponentApplicationModelProvider.cs │ └── SubControllerApplicationModelProvider.cs ├── Executorlibs.AspNetCore.Mvc.csproj ├── SubAreaAttribute.cs ├── SubComponentAttribute.cs └── SubControllerAttribute.cs ├── Executorlibs.AspNetCore.Routing ├── DependencyInjection │ └── RoutingServiceCollectionExtensions.cs ├── Executorlibs.AspNetCore.Routing.csproj └── Matching │ └── ModifiedAcceptsMatcherPolicy.cs ├── Executorlibs.Bilibili.Protocol ├── Builders │ └── BilibiliDanmakuFrameworkBuilder.cs ├── Clients │ ├── BilibiliDanmakuProtocol.cs │ ├── DanmakuClientBase.cs │ ├── IDanmakuClient.cs │ ├── TcpDanmakuClientBase.cs │ ├── TcpDanmakuClientV2.cs │ ├── TcpDanmakuClientV3.cs │ ├── WsDanmakuClientBase.cs │ ├── WsDanmakuClientV2.cs │ └── WsDanmakuClientV3.cs ├── Executorlibs.Bilibili.Protocol.csproj ├── Handlers │ ├── IBilibiliMessageHandler.cs │ ├── IContravarianceBilibiliMessageHandler.cs │ └── IInvarianceBilibiliMessageHandler.cs ├── Invokers │ ├── Attributes │ │ ├── RegisterBilibiliMessageSubscriptionAttribute.cs │ │ └── RegisterBilibiliMessageSubscriptionResolverAttribute.cs │ ├── BilibiliMessageHandlerInvoker.cs │ ├── BilibiliMessageSubscription.cs │ ├── BilibiliMessageSubscriptionResolver.cs │ └── IBilibiliMessageSubscription.cs ├── Models │ ├── Danmaku │ │ ├── AnchorLotteryMessage.cs │ │ ├── AnchorLotteryResultMessage.cs │ │ ├── BeatstormMessage.cs │ │ ├── CommonLotteryMessage.cs │ │ ├── CommonLotteryResultMessage.cs │ │ ├── CutOffMessage.cs │ │ ├── DanmakuBaseMessage.cs │ │ ├── DanmakuLotteryMessage.cs │ │ ├── DanmakuLotteryResultMessage.cs │ │ ├── DanmakuMessage.cs │ │ ├── EnterMessage.cs │ │ ├── FollowMessage.cs │ │ ├── GuardBuyMessage.cs │ │ ├── IAdminMessage.cs │ │ ├── IGuardMessage.cs │ │ ├── ILordMessage.cs │ │ ├── InteractMessage.cs │ │ ├── LiveEndMessage.cs │ │ ├── LiveManagementMessage.cs │ │ ├── LiveStartMessage.cs │ │ ├── Medal.cs │ │ ├── OnlineCountMessage.cs │ │ ├── PkStartMessage.cs │ │ ├── PopularityMessage.cs │ │ ├── RedPocketMessage.cs │ │ ├── RoomChangeMessage.cs │ │ ├── RoomLockMessage.cs │ │ ├── SendGiftBaseMessage.cs │ │ ├── SendGiftMessage.cs │ │ ├── SuperChatMessage.cs │ │ ├── Title.cs │ │ ├── UserMessage.cs │ │ ├── UserMutedMessage.cs │ │ ├── WarningMessage.cs │ │ ├── WelcomeGuardMessage.cs │ │ └── WelcomeMessage.cs │ ├── DanmakuServerInfo.cs │ ├── Enums │ │ ├── DanmakuMode.cs │ │ ├── GuardType.cs │ │ ├── InteractType.cs │ │ ├── InteractUserType.cs │ │ └── LordType.cs │ └── General │ │ ├── BilibiliMessage.cs │ │ ├── ConnectedMessage.cs │ │ ├── DisconnectedMessage.cs │ │ └── UnknownMessage.cs ├── Options │ └── DanmakuClientOptions.cs ├── Parsers │ ├── AnchorLotteryParser.cs │ ├── AnchorLotteryResultParser.cs │ ├── Attributes │ │ ├── RegisterBilibiliParserAttribute.cs │ │ └── RegisterBilibiliParserResolverAttribute.cs │ ├── BeatstormParser.cs │ ├── BilibiliMappableMessageParser.cs │ ├── BilibiliMessageParser.cs │ ├── BilibiliMessageParserResolver.cs │ ├── CommonLotteryResultParser.cs │ ├── CutOffParser.cs │ ├── DanmakuFallbackParser.cs │ ├── DanmakuLotteryParser.cs │ ├── DanmakuLotteryResultParser.cs │ ├── DanmakuParser.cs │ ├── EnterParser.cs │ ├── FollowParser.cs │ ├── GuardBuyParser.cs │ ├── IMappableBilibiliMessageParser.cs │ ├── InteractBaseParser.cs │ ├── InteractParser.cs │ ├── LiveEndParser.cs │ ├── LiveManagementParser.cs │ ├── LiveStartParser.cs │ ├── OnlineCountParser.cs │ ├── PkBaseParser.cs │ ├── PkEndParser.cs │ ├── PkStartParser.cs │ ├── RedPocketParser.cs │ ├── RoomChangeParser.cs │ ├── RoomLockParser.cs │ ├── SendGiftParser.cs │ ├── SimpleBilibiliMessageParser.cs │ ├── SuperChatParser.cs │ ├── UnknownMessageParser.cs │ ├── UserMutedParser.cs │ ├── UserToastGuardBuyParser.cs │ ├── WarningParser.cs │ ├── WelcomeGuardParser.cs │ └── WelcomeParser.cs └── Services │ └── DanmakuServerProvider.cs ├── Executorlibs.Caching ├── Abstractions │ ├── CacheEntryExtensions.cs │ ├── CacheExtensions.cs │ ├── ICacheEntry.cs │ └── IMemoryCache.cs ├── CacheEntry.CacheEntryState.cs ├── CacheEntry.CacheEntryTokens.cs ├── CacheEntry.cs ├── CacheEntryHelper.cs ├── Executorlibs.Caching.csproj ├── MemoryCache.cs ├── MemoryCacheEntryOptions.cs ├── MemoryCacheOptions.cs ├── MemoryCacheServiceCollectionExtensions.cs ├── PostEvictionCallbackRegistration.cs └── PostEvictionDelegate.cs ├── Executorlibs.Examples ├── BilibiliDanmakuProtocolTest.cs └── Executorlibs.Examples.csproj ├── Executorlibs.FFmpegInterop.NativeAssets.Win32 ├── Executorlibs.FFmpegInterop.NativeAssets.Win32.nuspec ├── Executorlibs.FFmpegInterop.NativeAssets.Win32.props ├── _._ └── runtimes │ └── win-x64 │ └── native │ ├── avcodec-59.dll │ ├── avdevice-59.dll │ ├── avfilter-8.dll │ ├── avformat-59.dll │ ├── avutil-57.dll │ ├── postproc-56.dll │ ├── swresample-4.dll │ └── swscale-6.dll ├── Executorlibs.FFmpegInterop ├── AVCodecNativeMethods.cs ├── AVFormatNativeMethods.cs ├── AVUtilNativeMethods.cs ├── Executorlibs.FFmpegInterop.csproj ├── Models │ ├── AVCodec.cs │ ├── AVCodecContext.cs │ ├── AVCodecParameters.cs │ ├── AVDictionary.cs │ ├── AVFormatContext.cs │ ├── AVFrame.cs │ ├── AVIOContext.cs │ ├── AVInputFormat.cs │ ├── AVMediaType.cs │ ├── AVPacket.cs │ ├── AVSampleFormat.cs │ ├── AVSeek.cs │ └── AVStream.cs └── SwresampleNativeMethods.cs ├── Executorlibs.Huya.Protocol ├── Clients │ ├── HuyaClientBase.cs │ └── IHuyaClient.cs ├── Executorlibs.Huya.Protocol.csproj ├── Handlers │ ├── IContravarianceHuyaMessageHandler.cs │ ├── IHuyaMessageHandler.cs │ └── IInvarianceHuyaMessageHandler.cs ├── Invokers │ ├── Attributes │ │ ├── RegisterHuyaMessageSubscriptionAttribute.cs │ │ └── RegisterHuyaMessageSubscriptionResolverAttribute.cs │ ├── HuyaMessageHandlerInvoker.cs │ ├── HuyaMessageSubscription.cs │ ├── HuyaMessageSubscriptionResolver.cs │ └── IHuyaMessageSubscription.cs ├── Models │ ├── CommentMessage.cs │ ├── General │ │ ├── HuyaMessage.cs │ │ └── UnknownMessage.cs │ ├── HuyaMsgType.cs │ ├── MessageBulletFormat.cs │ ├── MessageFormat.cs │ ├── MessageSenderInfo.cs │ ├── NobleLevelInfo.cs │ ├── PerSuffixInfo.cs │ ├── PushMessage.cs │ ├── PushMessageV2.cs │ ├── TagInfo.cs │ ├── UserInfo.cs │ ├── WebSocketCommand.cs │ ├── WsMsgItem.cs │ └── WupMessage.cs ├── Options │ └── HuyaClientOptions.cs ├── Parsers │ ├── Attributes │ │ ├── RegisterHuyaParserAttribute.cs │ │ └── RegisterHuyaParserResolverAttribute.cs │ ├── HuyaMessageParser.cs │ └── HuyaMessageParserResolver.cs └── Services │ └── IHuyaRequestDispatcher.cs ├── Executorlibs.MessageFramework ├── Attributes │ └── RegisterBaseAttribute.cs ├── Builders │ └── MessageFrameworkBuilder.cs ├── Clients │ ├── MessageClient.cs │ └── MessageDispatchClient.cs ├── Executorlibs.MessageFramework.csproj ├── Handlers │ ├── IContravarianceMessageHandler.cs │ ├── IInvarianceMessageHandler.cs │ └── IMessageHandler.cs ├── Invoking │ ├── Attributes │ │ ├── RegisterMessageSubscriptionAttribute.cs │ │ └── RegisterMessageSubscriptionResolverAttribute.cs │ ├── DynamicHandlerRegistration.cs │ ├── IMessageSubscription.cs │ ├── MessageHandlerInvoker.cs │ ├── MessageSubscription.Enumerator.cs │ ├── MessageSubscription.RegistrationNode.cs │ ├── MessageSubscription.Registrations.cs │ ├── MessageSubscription.cs │ ├── MessageSubscriptionResolver.cs │ └── PluginResistration.cs ├── Models │ └── General │ │ └── Message.cs ├── Parsers │ ├── Attributes │ │ ├── RegisterParserAttribute.cs │ │ ├── RegisterParserResolverAttribute.cs │ │ └── SuppressAutoMappingAttribute.cs │ ├── IMappableMessageParser.cs │ ├── IMessageParser.cs │ └── IMessageParserResolver.cs └── UInt32Lock.cs ├── Executorlibs.NeteaseMusic ├── Apis │ ├── NeteaseMusicApis.CheckMusicStatus.cs │ ├── NeteaseMusicApis.GetCsrfToken.cs │ ├── NeteaseMusicApis.GetLyric.cs │ ├── NeteaseMusicApis.GetPlayList.cs │ ├── NeteaseMusicApis.GetPlayerUrlResponse.cs │ ├── NeteaseMusicApis.GetSongDetail.cs │ ├── NeteaseMusicApis.GetSongsUrl.cs │ ├── NeteaseMusicApis.GetUserInfo.cs │ ├── NeteaseMusicApis.GetWebPlayerUrlResponse.cs │ ├── NeteaseMusicApis.Login.cs │ ├── NeteaseMusicApis.Logout.cs │ ├── NeteaseMusicApis.Search.cs │ ├── NeteaseMusicApis.SearchPlaylistAsync.cs │ └── NeteaseMusicApis.SearchSongs.cs ├── Crypto │ ├── CryptoHelper.cs │ └── RSANoPadding.cs ├── Exceptions │ ├── LoginFailedException.cs │ ├── NoSuchPlaylistException.cs │ ├── NoSuchSongException.cs │ ├── PlaylistAccessDeniedException.cs │ └── PlaylistException.cs ├── Executorlibs.NeteaseMusic.csproj └── Models │ ├── AlbumInfo.cs │ ├── ArtistInfo.cs │ ├── DownloadSongInfo.cs │ ├── LyricInfo.cs │ ├── PlaylistInfo.cs │ ├── Quality.cs │ ├── SearchType.cs │ ├── SongInfo.cs │ ├── UnikeyStatus.cs │ └── UserInfo.cs ├── Executorlibs.Shared.Protocol ├── Clients │ └── IProtocolClient.cs ├── Executorlibs.Shared.Protocol.csproj └── Models │ ├── Danmaku │ ├── ICutOffMessage.cs │ ├── IDanmakuBaseMessage.cs │ ├── IDanmakuMessage.cs │ ├── IEnterMessage.cs │ ├── IFollowMessage.cs │ ├── ILiveEndMessage.cs │ ├── ILiveManagementMessage.cs │ ├── ILiveStartMessage.cs │ ├── IMedal.cs │ ├── IRoomLockMessage.cs │ ├── ISendGiftBaseMessage.cs │ ├── ITitle.cs │ ├── IUserMessage.cs │ ├── IUserMutedMessage.cs │ ├── IWarningMessage.cs │ └── PopularityMessage.cs │ └── General │ ├── ConnectedMessage.cs │ ├── ConnectionChangedMessage.cs │ ├── DisconnectedMessage.cs │ └── ProtocolMessage.cs ├── Executorlibs.Shared ├── Exceptions │ ├── DuplicateOperationException.cs │ ├── InvalidCookieException.cs │ ├── PermissionDeniedException.cs │ └── UnknownResponseException.cs ├── Executorlibs.Shared.csproj ├── Extensions │ ├── ExpressionBuilder.cs │ ├── HttpClientExtensions.PostByteArrayContent.cs │ ├── HttpClientExtensions.PostEmptyContent.cs │ ├── HttpClientExtensions.PostHttpContent.cs │ ├── HttpClientExtensions.PostJsonContent.cs │ ├── HttpClientExtensions.PostStringContent.cs │ ├── HttpClientExtensions.Stream.cs │ ├── HttpClientExtensions.cs │ ├── HttpRequestHeadersExtension.cs │ ├── JsonElementExtensions.cs │ ├── SocketExtension.cs │ ├── StreamExtensions.cs │ └── WebSocketExtensions.cs ├── Helpers │ ├── HexConverter.cs │ ├── RsaHelper.cs │ └── StringHelper.cs ├── JsonConverters │ ├── ChangeTypeJsonConverter.cs │ ├── DateTimeJsonConverter.cs │ ├── DictValuesConverter.cs │ ├── Double2StringJsonConverter.cs │ ├── DoubleJsonConverterAttribute.cs │ ├── NonStringKeyConverter.cs │ ├── NullableJsonConverter.cs │ ├── TimeSpanJsonConverter.cs │ └── UnixTimeStampJsonConverter.cs ├── Net │ └── Http │ │ └── PCHttpClient.cs ├── System │ ├── Collections │ │ └── Concurrent │ │ │ └── ConcurrentHashSet.cs │ └── Net │ │ └── Http │ │ └── HttpClientv2.cs ├── UnsafeHelper.cs └── Utils.cs └── Executorlibs.TarProtocol ├── Exceptions ├── MalformedTarMessageException.cs └── TarTypeMismatchException.cs ├── Executorlibs.TarProtocol.csproj ├── IO ├── TarReader.cs └── TarWriter.cs └── Models ├── IReadableTarType.cs ├── ITarType.cs ├── IWritableTarType.cs ├── Primitives ├── TarAny.cs ├── TarByte.cs ├── TarByteArray.cs ├── TarDictionary.cs ├── TarDouble.cs ├── TarFloat.cs ├── TarInt16.cs ├── TarInt32.cs ├── TarInt64.cs ├── TarList.cs ├── TarString.cs ├── TarStruct.cs ├── TarStructBegin.cs ├── TarStructEnd.cs └── TarZero.cs ├── TarHeader.cs └── TarType.cs /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | net7.0;net6.0;net5.0;netstandard2.1;netstandard2.0 4 | 10.0 5 | enable 6 | true 7 | Executor 8 | Executor 9 | 1.4.0.0 10 | 1.4.0.0 11 | 1.4.0.0 12 | Copyright © Executor 2021 13 | MIT 14 | https://github.com/Executor-Cheng/Executorlibs 15 | true 16 | https://github.com/Executor-Cheng/Executorlibs 17 | git 18 | 19 | true 20 | true 21 | true 22 | 1701;1702;1573;1591; 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Executor-Cheng 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Executorlibs 2 | 3 | 写给自己用的一些库, 大多数和破站有关 4 | 5 | ### 各个项目 6 | - `Executorlibs.Examples` 一些例子的项目 7 | - `Executorlibs.MessageFramework` 自写自用消息框架 8 | - `Executorlibs.Shared` 共享的一些类 9 | - `Executorlibs.Shared.Protocol` 消息客户端专用的一些定义 10 | - `Executorlibs.Bilibili.Protocol` 自制的Bilibili直播平台的消息客户端 11 | - `Executorlibs.TarProtocol` 自制的Tars(Taf)消息框架实现 ~~用了一些(不少)黑科技~~ 12 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Identity/ClaimLoadingOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.AspNetCore.Identity 2 | { 3 | public class ClaimsLoadingOptions 4 | { 5 | public bool LoadUserId { get; set; } 6 | 7 | public bool LoadUserName { get; set; } 8 | 9 | public bool LoadUserEmail { get; set; } 10 | 11 | public bool LoadUserSecurityStamp { get; set; } 12 | 13 | public bool LoadUserClaims { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Identity/Executorlibs.AspNetCore.Identity.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net7.0;net6.0;net5.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Identity/IRoleStore.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | using Microsoft.EntityFrameworkCore; 3 | 4 | namespace Executorlibs.AspNetCore.Identity 5 | { 6 | public interface IRoleStore : IRoleStore where TRole : class where TContext : DbContext 7 | { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Identity/IUserStore.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | using Microsoft.EntityFrameworkCore; 3 | 4 | namespace Executorlibs.AspNetCore.Identity 5 | { 6 | public interface IUserStore : IUserStore where TUser : class where TContext : DbContext 7 | { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Identity/IdentityDbContextAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Executorlibs.AspNetCore.Identity 4 | { 5 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] 6 | public class IdentityDbContextAttribute : Attribute 7 | { 8 | public Type DbContextType { get; } 9 | 10 | public IdentityDbContextAttribute(Type dbContextType) 11 | { 12 | DbContextType = dbContextType; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Identity/IdentityRoleStoreProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Executorlibs.AspNetCore.Identity 6 | { 7 | public interface IIdentityRoleStoreProvider where TRole : class where TContext : DbContext 8 | { 9 | IRoleStore GetRoleStore(); 10 | } 11 | 12 | public class IdentityRoleStoreProvider : IIdentityRoleStoreProvider where TRole : class where TContext : DbContext 13 | { 14 | protected readonly IServiceProvider _services; 15 | 16 | protected readonly IIdentityRoleStoreResolver _resolver; 17 | 18 | public IdentityRoleStoreProvider(IServiceProvider services, IIdentityRoleStoreResolver resolver) 19 | { 20 | _services = services; 21 | _resolver = resolver; 22 | } 23 | 24 | public virtual IRoleStore GetRoleStore() 25 | { 26 | return (IRoleStore)_services.GetRequiredService(_resolver.ResolveRoleStoreType(typeof(TContext))); 27 | } 28 | } 29 | 30 | public sealed class DefaultIdentityRoleStoreProvider : IdentityRoleStoreProvider where TRole : class where TContext : DbContext 31 | { 32 | public DefaultIdentityRoleStoreProvider(IServiceProvider services, IIdentityRoleStoreResolver resolver) : base(services, resolver) 33 | { 34 | 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Identity/IdentityUserStoreProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Executorlibs.AspNetCore.Identity 6 | { 7 | public interface IIdentityUserStoreProvider where TUser : class where TContext : DbContext 8 | { 9 | IUserStore GetUserStore(); 10 | } 11 | 12 | public class IdentityUserStoreProvider : IIdentityUserStoreProvider where TUser : class where TContext : DbContext 13 | { 14 | protected readonly IServiceProvider _services; 15 | 16 | protected readonly IIdentityUserStoreResolver _resolver; 17 | 18 | public IdentityUserStoreProvider(IServiceProvider services, IIdentityUserStoreResolver resolver) 19 | { 20 | _services = services; 21 | _resolver = resolver; 22 | } 23 | 24 | public virtual IUserStore GetUserStore() 25 | { 26 | return (IUserStore)_services.GetRequiredService(_resolver.ResolveUserStoreType(typeof(TContext))); 27 | } 28 | } 29 | 30 | public sealed class DefaultIdentityUserStoreProvider : IdentityUserStoreProvider where TUser : class where TContext : DbContext 31 | { 32 | public DefaultIdentityUserStoreProvider(IServiceProvider services, IIdentityUserStoreResolver resolver) : base(services, resolver) 33 | { 34 | 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Identity/RoleClaimsLoadingOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.AspNetCore.Identity 2 | { 3 | public class RoleClaimsLoadingOptions : ClaimsLoadingOptions 4 | { 5 | public bool LoadUserRoles { get; set; } 6 | 7 | public bool LoadRoleClaims { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Identity/RoleManager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Microsoft.AspNetCore.Identity; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.Extensions.Logging; 5 | 6 | namespace Executorlibs.AspNetCore.Identity 7 | { 8 | public class RoleManager : RoleManager where TRole : class where TContext : DbContext 9 | { 10 | public RoleManager(IRoleStore store, IEnumerable> roleValidators, ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors, ILogger> logger) 11 | : base(store, roleValidators, keyNormalizer, errors, logger) 12 | { 13 | 14 | } 15 | } 16 | 17 | public sealed class DefaultRoleManager : RoleManager where TRole : class where TContext : DbContext 18 | { 19 | public DefaultRoleManager(IIdentityRoleStoreProvider storeProvider, IEnumerable> roleValidators, ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors, ILogger> logger) 20 | : base(storeProvider.GetRoleStore(), roleValidators, keyNormalizer, errors, logger) 21 | { 22 | 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Identity/RoleStoreProxy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Identity; 3 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore; 5 | 6 | #pragma warning disable CS8613 // Nullability of reference types in return type doesn't match implicitly implemented member. 7 | namespace Executorlibs.AspNetCore.Identity 8 | { 9 | internal sealed class RoleStoreProxy : RoleStore, IRoleStore 10 | where TRole : IdentityRole 11 | where TKey : IEquatable 12 | where TContext : DbContext 13 | { 14 | public RoleStoreProxy(TContext context, IdentityErrorDescriber? describer = null) : base(context, describer) 15 | { 16 | 17 | } 18 | } 19 | 20 | internal sealed class RoleStoreProxy : RoleStore, IRoleStore 21 | where TRole : IdentityRole 22 | where TKey : IEquatable 23 | where TContext : DbContext 24 | where TUserRole : IdentityUserRole, new() 25 | where TRoleClaim : IdentityRoleClaim, new() 26 | { 27 | public RoleStoreProxy(TContext context, IdentityErrorDescriber? describer = null) : base(context, describer) 28 | { 29 | 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Identity/SignInManager.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authentication; 2 | using Microsoft.AspNetCore.Http; 3 | using Microsoft.AspNetCore.Identity; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.Extensions.Logging; 6 | using Microsoft.Extensions.Options; 7 | 8 | namespace Executorlibs.AspNetCore.Identity 9 | { 10 | public class SignInManager : SignInManager where TUser : class where TContext : DbContext 11 | { 12 | public SignInManager(UserManager userManager, IHttpContextAccessor contextAccessor, IUserClaimsPrincipalFactory claimsFactory, IOptions optionsAccessor, ILogger> logger, IAuthenticationSchemeProvider schemes, IUserConfirmation confirmation) : base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, confirmation) 13 | { 14 | 15 | } 16 | } 17 | 18 | public sealed class DefaultSignInManager : SignInManager where TUser : class where TContext : DbContext 19 | { 20 | public DefaultSignInManager(UserManager userManager, IHttpContextAccessor contextAccessor, IUserClaimsPrincipalFactoryProvider claimsFactoryProvider, IOptions optionsAccessor, ILogger> logger, IAuthenticationSchemeProvider schemes, IUserConfirmation confirmation) : base(userManager, contextAccessor, claimsFactoryProvider.GetFactory(), optionsAccessor, logger, schemes, confirmation) 21 | { 22 | 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Identity/TypeResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Executorlibs.AspNetCore.Identity 4 | { 5 | public abstract class TypeResolver 6 | { 7 | protected static Type? FindGenericBaseType(Type currentType, Type genericBaseType) 8 | { 9 | Type? type = currentType; 10 | do 11 | { 12 | if (type.IsGenericType && type.GetGenericTypeDefinition() == genericBaseType) 13 | { 14 | return type; 15 | } 16 | } 17 | while ((type = type.BaseType) != null); 18 | return null; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Identity/UserClaimsPrincipalFactoryProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Identity; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.Extensions.DependencyInjection; 5 | 6 | namespace Executorlibs.AspNetCore.Identity 7 | { 8 | public interface IUserClaimsPrincipalFactoryProvider where TUser : class where TContext : DbContext 9 | { 10 | IUserClaimsPrincipalFactory GetFactory(); 11 | } 12 | 13 | public class UserClaimsPrincipalFactoryProvider : IUserClaimsPrincipalFactoryProvider where TUser : class where TContext : DbContext 14 | { 15 | protected readonly IServiceProvider _services; 16 | 17 | protected readonly IUserClaimsPrincipalFactoryResolver _resolver; 18 | 19 | public UserClaimsPrincipalFactoryProvider(IServiceProvider services, IUserClaimsPrincipalFactoryResolver resolver) 20 | { 21 | _services = services; 22 | _resolver = resolver; 23 | } 24 | 25 | public virtual IUserClaimsPrincipalFactory GetFactory() 26 | { 27 | return (IUserClaimsPrincipalFactory)_services.GetRequiredService(_resolver.ResolveFactoryType(typeof(TContext))); 28 | } 29 | } 30 | 31 | public sealed class DefaultUserClaimsPrincipalFactoryProvider : UserClaimsPrincipalFactoryProvider where TUser : class where TContext : DbContext 32 | { 33 | public DefaultUserClaimsPrincipalFactoryProvider(IServiceProvider services, IUserClaimsPrincipalFactoryResolver resolver) : base(services, resolver) 34 | { 35 | 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Identity/UserOnlyStoreProxy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Identity; 3 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore; 5 | 6 | #pragma warning disable CS8613 // Nullability of reference types in return type doesn't match implicitly implemented member. 7 | namespace Executorlibs.AspNetCore.Identity 8 | { 9 | internal sealed class UserOnlyStoreProxy : UserOnlyStore, IUserStore 10 | where TUser : IdentityUser 11 | where TContext : DbContext 12 | where TKey : IEquatable 13 | { 14 | public UserOnlyStoreProxy(TContext context, IdentityErrorDescriber? describer = null) : base(context, describer) 15 | { 16 | 17 | } 18 | } 19 | 20 | internal sealed class UserOnlyStoreProxy : UserOnlyStore, IUserStore 21 | where TUser : IdentityUser 22 | where TContext : DbContext 23 | where TKey : IEquatable 24 | where TUserClaim : IdentityUserClaim, new() 25 | where TUserLogin : IdentityUserLogin, new() 26 | where TUserToken : IdentityUserToken, new() 27 | { 28 | public UserOnlyStoreProxy(TContext context, IdentityErrorDescriber? describer = null) : base(context, describer) 29 | { 30 | 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Mvc/ApplicationModels/SubAreaApplicationModelProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.AspNetCore.Mvc.ApplicationModels 2 | { 3 | public class SubAreaApplicationModelProvider : SubComponentApplicationModelProvider 4 | { 5 | public override int Order => -1000; 6 | 7 | protected override string SubComponentName => "subarea"; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Mvc/ApplicationModels/SubControllerApplicationModelProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.AspNetCore.Mvc.ApplicationModels 2 | { 3 | public class SubControllerApplicationModelProvider : SubComponentApplicationModelProvider 4 | { 5 | public override int Order => -1000; 6 | 7 | protected override string SubComponentName => "subcontroller"; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Mvc/Executorlibs.AspNetCore.Mvc.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net7.0;net6.0;net5.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Mvc/SubAreaAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.AspNetCore.Mvc 2 | { 3 | public sealed class SubAreaAttribute : SubComponentAttribute 4 | { 5 | public string SubAreaName { get; } 6 | 7 | public override string SubComponentName => SubAreaName; 8 | 9 | public SubAreaAttribute(string subAreaName) 10 | { 11 | SubAreaName = subAreaName; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Mvc/SubComponentAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Executorlibs.AspNetCore.Mvc 4 | { 5 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] 6 | public abstract class SubComponentAttribute : Attribute 7 | { 8 | public abstract string SubComponentName { get; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Mvc/SubControllerAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.AspNetCore.Mvc 2 | { 3 | public sealed class SubControllerAttribute : SubComponentAttribute 4 | { 5 | public string SubControllerName { get; } 6 | 7 | public override string SubComponentName => SubControllerName; 8 | 9 | public SubControllerAttribute(string subControllerName) 10 | { 11 | SubControllerName = subControllerName; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Routing/DependencyInjection/RoutingServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Executorlibs.AspNetCore.Routing.Matching; 3 | using Microsoft.AspNetCore.Routing; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.DependencyInjection.Extensions; 6 | 7 | namespace Executorlibs.Extensions.DependencyInjection 8 | { 9 | public static class RoutingServiceCollectionExtensions 10 | { 11 | public static IServiceCollection ReplaceAcceptsMatcherPolicy(this IServiceCollection services) 12 | { 13 | ServiceDescriptor? acceptsMatcherPolicyDescriptor = services.FirstOrDefault(p => p.ServiceType == typeof(MatcherPolicy) && p.ImplementationType == ModifiedAcceptsMatcherPolicy.AcceptsMatcherPolicyType); 14 | if (acceptsMatcherPolicyDescriptor != null) 15 | { 16 | services.Remove(acceptsMatcherPolicyDescriptor); 17 | services.TryAddSingleton(ModifiedAcceptsMatcherPolicy.AcceptsMatcherPolicyType); 18 | services.TryAddEnumerable(ServiceDescriptor.Singleton(typeof(MatcherPolicy), typeof(ModifiedAcceptsMatcherPolicy))); 19 | } 20 | return services; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Executorlibs.AspNetCore.Routing/Executorlibs.AspNetCore.Routing.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net7.0;net6.0;net5.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Clients/IDanmakuClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Executorlibs.Shared.Protocol.Clients; 3 | 4 | namespace Executorlibs.Bilibili.Protocol.Clients 5 | { 6 | public interface IDanmakuClient : IProtocolClient, IDisposable 7 | { 8 | int RoomId { get; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Executorlibs.Bilibili.Protocol.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Danmaku framework for bilibili live platform. 5 | bilibili, danmaku, danmu 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Handlers/IContravarianceBilibiliMessageHandler.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Bilibili.Protocol.Clients; 2 | using Executorlibs.Bilibili.Protocol.Models.General; 3 | using Executorlibs.MessageFramework.Handlers; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Handlers 6 | { 7 | public interface IContravarianceBilibiliMessageHandler : IBilibiliMessageHandler, IContravarianceMessageHandler where TMessage : IBilibiliMessage 8 | { 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Handlers/IInvarianceBilibiliMessageHandler.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Bilibili.Protocol.Clients; 2 | using Executorlibs.Bilibili.Protocol.Models.General; 3 | using Executorlibs.MessageFramework.Handlers; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Handlers 6 | { 7 | public interface IInvarianceBilibiliMessageHandler : IBilibiliMessageHandler, IInvarianceMessageHandler where TMessage : IBilibiliMessage 8 | { 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Invokers/Attributes/RegisterBilibiliMessageSubscriptionResolverAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Executorlibs.MessageFramework.Invoking.Attributes; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Invokers.Attributes 6 | { 7 | public class RegisterBilibiliMessageSubscriptionResolverAttribute : RegisterMessageSubscriptionResolverAttribute 8 | { 9 | public RegisterBilibiliMessageSubscriptionResolverAttribute(Type implementationType) : this(implementationType, null) 10 | { 11 | 12 | } 13 | 14 | public RegisterBilibiliMessageSubscriptionResolverAttribute(Type implementationType, ServiceLifetime? lifetime) : base(implementationType, lifetime) 15 | { 16 | 17 | } 18 | 19 | protected override Type GetServiceType(Type implementationType) 20 | { 21 | var interfaceType = typeof(IBilibiliMessageSubscriptionResolver); 22 | if (interfaceType.IsAssignableFrom(implementationType)) 23 | { 24 | return interfaceType; 25 | } 26 | throw new ArgumentException($"给定的 {implementationType.Name} 不实现 {interfaceType.Name}", nameof(implementationType)); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Invokers/IBilibiliMessageSubscription.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Executorlibs.Bilibili.Protocol.Clients; 3 | using Executorlibs.Bilibili.Protocol.Handlers; 4 | using Executorlibs.Bilibili.Protocol.Models.General; 5 | using Executorlibs.MessageFramework.Invoking; 6 | 7 | namespace Executorlibs.Bilibili.Protocol.Invokers 8 | { 9 | public interface IBilibiliMessageSubscription : IMessageSubscription, IBilibiliMessageHandler 10 | { 11 | 12 | } 13 | 14 | public interface IBilibiliMessageSubscription : IBilibiliMessageSubscription, IBilibiliMessageHandler where TMessage : IBilibiliMessage 15 | { 16 | #if !NETSTANDARD2_0 17 | Task IBilibiliMessageHandler.HandleMessageAsync(IDanmakuClient client, IBilibiliMessage message) 18 | => HandleMessageAsync(client, (TMessage)message); 19 | #endif 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/AnchorLotteryMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 2 | { 3 | public interface IAnchorLotteryMessage : ICommonLotteryMessage 4 | { 5 | 6 | } 7 | 8 | public class AnchorLotteryMessage : CommonLotteryMessage, IAnchorLotteryMessage 9 | { 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/AnchorLotteryResultMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 2 | { 3 | public interface IAnchorLotteryResultMessage : ICommonLotteryResultMessage 4 | { 5 | 6 | } 7 | 8 | public class AnchorLotteryResultMessage : CommonLotteryResultMessage, IAnchorLotteryResultMessage 9 | { 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/BeatstormMessage.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Bilibili.Protocol.Models.General; 2 | 3 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 4 | { 5 | public interface IBeatstormMessage : IBilibiliMessage 6 | { 7 | bool Action { get; } 8 | 9 | int Count { get; } 10 | 11 | string? Content { get; } 12 | } 13 | 14 | public class BeatstormMessage : BilibiliMessage, IBeatstormMessage 15 | { 16 | public bool Action { get; set; } 17 | 18 | public int Count { get; set; } 19 | 20 | public string? Content { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/CommonLotteryResultMessage.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Bilibili.Protocol.Models.General; 2 | 3 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 4 | { 5 | public interface ICommonLotteryResultMessage : IBilibiliMessage 6 | { 7 | string AwardName { get; } 8 | 9 | int AwardNum { get; } 10 | 11 | (string, long)[] AwardUsers { get; } 12 | } 13 | 14 | public abstract class CommonLotteryResultMessage : BilibiliMessage, ICommonLotteryResultMessage 15 | { 16 | public string AwardName { get; set; } = null!; 17 | 18 | public int AwardNum { get; set; } 19 | 20 | public (string, long)[] AwardUsers { get; set; } = null!; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/CutOffMessage.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Bilibili.Protocol.Parsers; 2 | using Executorlibs.Bilibili.Protocol.Parsers.Attributes; 3 | //using ISharedCutOffMessage = LiveRoomMonitorV3.Shared.Protocol.Models.Danmaku.ICutOffMessage; // summary broken up 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 6 | { 7 | /// 8 | /// 表示当前直播间被直播管理员切断消息的接口 9 | /// 10 | /// 11 | /// 消息来源是 Bilibili 直播平台 12 | /// 继承自以下接口: 13 | /// 14 | /// 15 | /// 16 | /// 17 | /// 18 | [RegisterBilibiliParser(typeof(CutOffParser))] 19 | public interface ICutOffMessage : ILiveManagementMessage, Executorlibs.Shared.Protocol.Models.Danmaku.ICutOffMessage 20 | { 21 | 22 | } 23 | 24 | /// 25 | /// 表示一条直播间被直播管理员切断消息 26 | /// 27 | /// 28 | /// 消息来源是 Bilibili 直播平台 29 | /// 30 | public class CutOffMessage : LiveManagementMessage, ICutOffMessage 31 | { 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/DanmakuBaseMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using Executorlibs.Shared.Protocol.Models.Danmaku; 3 | 4 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 5 | { 6 | /// 7 | /// 表示弹幕的基本信息接口 8 | /// 9 | /// 10 | /// 继承自以下接口: 11 | /// 12 | /// 13 | /// 14 | /// 15 | /// 16 | public interface IDanmakuBaseMessage : IDanmakuBaseMessage, IUserMessage 17 | { 18 | /// 19 | /// 弹幕Token 20 | /// 21 | int Token { get; } 22 | /// 23 | /// 用户等级 24 | /// 25 | int Level { get; } 26 | } 27 | 28 | /// 29 | /// 实现弹幕的基本信息接口的抽象类 30 | /// 31 | public abstract class DanmakuBaseMessage : UserMessage, IDanmakuBaseMessage 32 | { 33 | ///// 34 | //public int Id { get; set; } 35 | 36 | /// 37 | public virtual int Token { get; set; } 38 | 39 | /// 40 | public string Comment { get; set; } = null!; 41 | 42 | /// 43 | public int Level { get; set; } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/DanmakuLotteryMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 4 | { 5 | public interface IDanmakuLotteryMessage : ICommonLotteryMessage 6 | { 7 | 8 | } 9 | 10 | public class DanmakuLotteryMessage : CommonLotteryMessage, IDanmakuLotteryMessage 11 | { 12 | public override int? GiftCost { get => null; set { } } 13 | 14 | public override string? GiftName { get => null; set { } } 15 | 16 | public override int? GiftNum { get => null; set { } } 17 | 18 | public DanmakuLotteryMessage() { } 19 | 20 | public DanmakuLotteryMessage(int id, int roomId, string danmaku, string awardName, int awardNum, int requireType, int requireValue, TimeSpan duration, DateTime endTime) : base(id, roomId, danmaku, awardName, awardNum, null, null, null, requireType, requireValue, duration, endTime) 21 | { 22 | 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/DanmakuLotteryResultMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 2 | { 3 | public interface IDanmakuLotteryResultMessage : ICommonLotteryResultMessage 4 | { 5 | 6 | } 7 | 8 | public class DanmakuLotteryResultMessage : CommonLotteryResultMessage, IDanmakuLotteryResultMessage 9 | { 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/FollowMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using Executorlibs.Bilibili.Protocol.Parsers; 3 | using Executorlibs.Bilibili.Protocol.Parsers.Attributes; 4 | using Executorlibs.Shared.Protocol.Models.Danmaku; 5 | 6 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 7 | { 8 | /// 9 | /// 表示用户关注直播间的接口 10 | /// 11 | /// 12 | /// 消息来源是 Bilibili 直播平台 13 | /// 继承自以下接口: 14 | /// 15 | /// 16 | /// 17 | /// 18 | /// 19 | [RegisterBilibiliParser(typeof(FollowParser))] 20 | public interface IFollowMessage : IFollowMessage, IInteractMessage 21 | { 22 | 23 | } 24 | 25 | /// 26 | /// 表示一条用户关注房间的消息 27 | /// 28 | public class FollowMessage : InteractMessage, IFollowMessage 29 | { 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/GuardBuyMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using Executorlibs.Bilibili.Protocol.Parsers; 3 | using Executorlibs.Bilibili.Protocol.Parsers.Attributes; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 6 | { 7 | /// 8 | /// 表示购买船员消息的接口 9 | /// 10 | /// 11 | /// 消息来源是 Bilibili 直播平台 12 | /// 继承自 13 | /// 14 | [RegisterBilibiliParser(typeof(GuardBuyParser))] 15 | public interface IGuardBuyMessage : ISendGiftBaseMessage 16 | { 17 | /// 18 | /// 内部订单号 19 | /// 20 | string? OrderId { get; } 21 | } 22 | 23 | /// 24 | /// 表示一条购买船员消息 25 | /// 26 | /// 27 | /// 消息来源是 Bilibili 直播平台 28 | /// 29 | [DebuggerDisplay("{Time.ToString(\"u\")[..^1],nq} [GuardBuy] {UserName,nq}[{UserId}]:{GiftName,nq}x{GiftCount}")] 30 | public class GuardBuyMessage : SendGiftBaseMessage, IGuardBuyMessage 31 | { 32 | /// 33 | public string? OrderId { get; set; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/IAdminMessage.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Bilibili.Protocol.Models.General; 2 | 3 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 4 | { 5 | /// 6 | /// 表示具有房管的信息接口 7 | /// 8 | public interface IAdminMessage : IBilibiliMessage 9 | { 10 | /// 11 | /// 是否为房管 12 | /// 13 | bool IsAdmin { get; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/IGuardMessage.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Bilibili.Protocol.Models.Enums; 2 | using Executorlibs.Bilibili.Protocol.Models.General; 3 | 4 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 5 | { 6 | /// 7 | /// 表示具有船员类型的信息接口 8 | /// 9 | public interface IGuardMessage : IBilibiliMessage 10 | { 11 | /// 12 | /// 船员类型 13 | /// 14 | GuardType GuardType { get; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/ILordMessage.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Bilibili.Protocol.Models.Enums; 2 | using Executorlibs.Bilibili.Protocol.Models.General; 3 | 4 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 5 | { 6 | /// 7 | /// 表示具有老爷类型的信息接口 8 | /// 9 | public interface ILordMessage : IBilibiliMessage 10 | { 11 | /// 12 | /// 老爷类型 13 | /// 14 | LordType LordType { get; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/InteractMessage.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Bilibili.Protocol.Models.Enums; 2 | using Executorlibs.Bilibili.Protocol.Parsers; 3 | using Executorlibs.Bilibili.Protocol.Parsers.Attributes; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 6 | { 7 | /// 8 | /// 表示用户互动消息的接口 9 | /// 10 | /// 11 | /// 消息来源是 Bilibili 直播平台 12 | /// 继承自 13 | /// 14 | [RegisterBilibiliParser(typeof(InteractParser))] 15 | public interface IInteractMessage : IUserMessage 16 | { 17 | /// 18 | /// 消息类型 19 | /// 20 | InteractType Type { get; } 21 | 22 | /// 23 | /// 用户类型 24 | /// 25 | InteractUserType UserType { get; } 26 | } 27 | 28 | /// 29 | /// 表示一条用户互动消息 30 | /// 31 | public class InteractMessage : UserMessage, IInteractMessage 32 | { 33 | /// 34 | public InteractType Type { get; set; } 35 | 36 | /// 37 | public InteractUserType UserType { get; set; } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/LiveEndMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using Executorlibs.Bilibili.Protocol.Models.General; 3 | using Executorlibs.Bilibili.Protocol.Parsers; 4 | using Executorlibs.Bilibili.Protocol.Parsers.Attributes; 5 | using Executorlibs.Shared.Protocol.Models.Danmaku; 6 | 7 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 8 | { 9 | /// 10 | /// 表示主播下播消息的接口 11 | /// 12 | /// 13 | /// 消息来源是 Bilibili 直播平台 14 | /// 继承自以下接口: 15 | /// 16 | /// 17 | /// 18 | /// 19 | /// 20 | [RegisterBilibiliParser(typeof(LiveEndParser))] 21 | public interface ILiveEndMessage : ILiveEndMessage, IBilibiliMessage 22 | { 23 | 24 | } 25 | 26 | /// 27 | /// 表示一条主播下播消息 28 | /// 29 | /// 30 | /// 消息来源是 Bilibili 直播平台 31 | /// 32 | public class LiveEndMessage : BilibiliMessage, ILiveEndMessage 33 | { 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/LiveManagementMessage.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Bilibili.Protocol.Models.General; 2 | using ISharedLiveManagementMessage = Executorlibs.Shared.Protocol.Models.Danmaku.ILiveManagementMessage; 3 | 4 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 5 | { 6 | public interface ILiveManagementMessage : IBilibiliMessage, ISharedLiveManagementMessage 7 | { 8 | 9 | } 10 | 11 | public abstract class LiveManagementMessage : BilibiliMessage, ILiveManagementMessage 12 | { 13 | public string? Message { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/LiveStartMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using Executorlibs.Bilibili.Protocol.Models.General; 3 | using Executorlibs.Bilibili.Protocol.Parsers; 4 | using Executorlibs.Bilibili.Protocol.Parsers.Attributes; 5 | using Executorlibs.Shared.Protocol.Models.Danmaku; 6 | 7 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 8 | { 9 | /// 10 | /// 表示主播开播消息的接口 11 | /// 12 | /// 13 | /// 消息来源是 Bilibili 直播平台 14 | /// 继承自以下接口: 15 | /// 16 | /// 17 | /// 18 | /// 19 | /// 20 | [RegisterBilibiliParser(typeof(LiveStartParser))] 21 | public interface ILiveStartMessage : ILiveStartMessage, IBilibiliMessage 22 | { 23 | 24 | } 25 | 26 | /// 27 | /// 表示一条主播开播消息 28 | /// 29 | /// 30 | /// 消息来源是 Bilibili 直播平台 31 | /// 32 | public class LiveStartMessage : BilibiliMessage, ILiveStartMessage 33 | { 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/Medal.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Shared.Protocol.Models.Danmaku; 2 | 3 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 4 | { 5 | /// 6 | /// 表示勋章信息的接口 7 | /// 8 | /// 9 | /// 此类型为 Bilibili 直播平台 专用 10 | /// 继承自 11 | /// 12 | public interface IMedal : IMedal 13 | { 14 | /// 15 | /// 前置小图标 16 | /// 17 | int? Badge { get; } 18 | } 19 | 20 | /// 21 | /// 表示勋章信息的类 22 | /// 23 | public class Medal : Medal, IMedal 24 | { 25 | /// 26 | public int? Badge { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/OnlineCountMessage.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Bilibili.Protocol.Models.General; 2 | 3 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 4 | { 5 | public interface IOnlineCountMessage : IBilibiliMessage 6 | { 7 | int Count { get; } 8 | } 9 | 10 | public class OnlineCountMessage : BilibiliMessage, IOnlineCountMessage 11 | { 12 | public int Count { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/PkStartMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Executorlibs.Bilibili.Protocol.Models.General; 3 | 4 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 5 | { 6 | public interface IPkBaseMessage : IBilibiliMessage 7 | { 8 | int RedRoomId { get; } 9 | 10 | int BlueRoomId { get; } 11 | 12 | DateTime EndTime { get; } 13 | } 14 | 15 | public interface IPkStartMessage : IPkBaseMessage 16 | { 17 | 18 | } 19 | 20 | public interface IPkEndMessage : IPkBaseMessage 21 | { 22 | long RedScore { get; } 23 | 24 | string RedBestUserName { get; } 25 | 26 | int RedMatchResult { get; } 27 | 28 | long BlueScore { get; } 29 | 30 | string BlueBestUserName { get; } 31 | 32 | int BlueMatchResult { get; } 33 | } 34 | 35 | public abstract class PkBaseMessage : BilibiliMessage, IPkBaseMessage 36 | { 37 | public int RedRoomId { get; set; } 38 | 39 | public int BlueRoomId { get; set; } 40 | 41 | public DateTime EndTime { get; set; } 42 | } 43 | 44 | public class PkStartMessage : PkBaseMessage, IPkStartMessage 45 | { 46 | 47 | } 48 | 49 | public class PkEndMessage : PkBaseMessage, IPkEndMessage 50 | { 51 | public long RedScore { get; set; } 52 | 53 | public string RedBestUserName { get; set; } = null!; 54 | 55 | public int RedMatchResult { get; set; } 56 | 57 | public long BlueScore { get; set; } 58 | 59 | public string BlueBestUserName { get; set; } = null!; 60 | 61 | public int BlueMatchResult { get; set; } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/PopularityMessage.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Bilibili.Protocol.Models.General; 2 | using ISharedPopularityMessage = Executorlibs.Shared.Protocol.Models.Danmaku.IPopularityMessage; 3 | 4 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 5 | { 6 | public interface IPopularityMessage : IBilibiliMessage, ISharedPopularityMessage 7 | { 8 | 9 | } 10 | 11 | public class PopularityMessage : BilibiliMessage, IPopularityMessage 12 | { 13 | public ulong Popularity { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/RedPocketMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Executorlibs.Bilibili.Protocol.Models.General; 3 | 4 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 5 | { 6 | public interface IRedPocketMessage : IBilibiliMessage 7 | { 8 | int Count { get; } 9 | 10 | string Content { get; } 11 | 12 | string Requirement { get; } 13 | 14 | string Sender { get; } 15 | 16 | long SenderId { get; } 17 | 18 | TimeSpan Duration { get; } 19 | } 20 | 21 | public class RedPocketMessage : BilibiliMessage, IRedPocketMessage 22 | { 23 | public int Count { get; set; } 24 | 25 | public string Content { get; set; } = null!; 26 | 27 | public string Requirement { get; set; } = null!; 28 | 29 | public string Sender { get; set; } = null!; 30 | 31 | public long SenderId { get; set; } 32 | 33 | public TimeSpan Duration { get; set; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/RoomChangeMessage.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Bilibili.Protocol.Models.General; 2 | 3 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 4 | { 5 | public interface IRoomChangeMessage : IBilibiliMessage 6 | { 7 | int AreaId { get; } 8 | 9 | int SubAreaId { get; } 10 | 11 | string Title { get; } 12 | } 13 | 14 | public class RoomChangeMessage : BilibiliMessage, IRoomChangeMessage 15 | { 16 | public int AreaId { get; set; } 17 | 18 | public int SubAreaId { get; set; } 19 | 20 | public string Title { get; set; } = null!; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/RoomLockMessage.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Bilibili.Protocol.Parsers; 2 | using Executorlibs.Bilibili.Protocol.Parsers.Attributes; 3 | //using ISharedRoomLockMessage = LiveRoomMonitorV3.Shared.Protocol.Models.Danmaku.IRoomLockMessage; // summary broken up 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 6 | { 7 | /// 8 | /// 表示当前直播间被直播管理员关闭消息的接口 9 | /// 10 | /// 11 | /// 消息来源是 Bilibili 直播平台 12 | /// 继承自以下接口: 13 | /// 14 | /// 15 | /// 16 | /// 17 | /// 18 | [RegisterBilibiliParser(typeof(RoomLockParser))] 19 | public interface IRoomLockMessage : ILiveManagementMessage, Executorlibs.Shared.Protocol.Models.Danmaku.IRoomLockMessage 20 | { 21 | 22 | } 23 | 24 | /// 25 | /// 表示一条当前直播间被直播管理员关闭消息 26 | /// 27 | /// 28 | /// 消息来源是 Bilibili 直播平台 29 | /// 30 | public class RoomLockMessage : LiveManagementMessage, IRoomLockMessage 31 | { 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/SendGiftMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using Executorlibs.Bilibili.Protocol.Parsers; 3 | using Executorlibs.Bilibili.Protocol.Parsers.Attributes; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 6 | { 7 | /// 8 | /// 表示赠送礼物的弹幕信息接口 9 | /// 10 | /// 11 | /// 消息来源是 Bilibili 直播平台 12 | /// 继承自 13 | /// 14 | [RegisterBilibiliParser(typeof(SendGiftParser))] 15 | public interface ISendGiftMessage : ISendGiftBaseMessage 16 | { 17 | /// 18 | /// 房间礼物积分 19 | /// 20 | long RoomCost { get; } 21 | } 22 | 23 | /// 24 | /// 表示一条赠送礼物的弹幕信息 25 | /// 26 | /// 27 | /// 消息来源是 Bilibili 直播平台 28 | /// 29 | [DebuggerDisplay("{Time.ToString(\"u\")[..^1],nq} [SendGift] {UserName,nq}[{UserId}]:{GiftName,nq}x{GiftCount}")] 30 | public class SendGiftMessage : SendGiftBaseMessage, ISendGiftMessage 31 | { 32 | /// 33 | public long RoomCost { get; set; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/UserMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using Executorlibs.Bilibili.Protocol.Models.General; 3 | using Executorlibs.Shared.Protocol.Models.Danmaku; 4 | #if NETSTANDARD2_0 5 | using ISharedUserMessage = Executorlibs.Shared.Protocol.Models.Danmaku.IUserMessage; 6 | #endif 7 | 8 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 9 | { 10 | /// 11 | /// 表示具有用户信息的接口 12 | /// 13 | /// 14 | /// 消息来源是 Bilibili 直播平台 15 | /// 继承自以下接口: 16 | /// 17 | /// 18 | /// 19 | /// 20 | /// 21 | public interface IUserMessage : IUserMessage, IBilibiliMessage 22 | { 23 | 24 | } 25 | 26 | /// 27 | /// 实现 的抽象类 28 | /// 29 | /// 30 | /// 消息来源是 Bilibili 直播平台 31 | /// 32 | public abstract class UserMessage : BilibiliMessage, IUserMessage 33 | { 34 | /// 35 | public string UserName { get; set; } = null!; 36 | 37 | /// 38 | public long UserId { get; set; } 39 | 40 | #if NETSTANDARD2_0 41 | object ISharedUserMessage.UserId => UserId!; 42 | #endif 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/UserMutedMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using Executorlibs.Bilibili.Protocol.Parsers; 3 | using Executorlibs.Bilibili.Protocol.Parsers.Attributes; 4 | using Executorlibs.Shared.Protocol.Models.Danmaku; 5 | 6 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 7 | { 8 | /// 9 | /// 表示用户被禁言消息的接口 10 | /// 11 | /// 12 | /// 消息来源是 Bilibili 直播平台 13 | /// 继承自以下接口: 14 | /// 15 | /// 16 | /// 17 | /// 18 | /// 19 | [RegisterBilibiliParser(typeof(UserMutedParser))] 20 | public interface IUserMutedMessage : IUserMutedMessage, IUserMessage 21 | { 22 | /// 23 | /// 是否为主播操作的禁言 24 | /// 25 | bool MasterOperation { get; } 26 | } 27 | 28 | /// 29 | /// 表示一条用户被禁言消息 30 | /// 31 | /// 32 | /// 消息来源是 Bilibili 直播平台 33 | /// 34 | public class UserMutedMessage : UserMessage, IUserMutedMessage 35 | { 36 | /// 37 | public bool MasterOperation { get; set; } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/WarningMessage.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Bilibili.Protocol.Parsers; 2 | using Executorlibs.Bilibili.Protocol.Parsers.Attributes; 3 | //using ISharedWarningMessage = LiveRoomMonitorV3.Shared.Protocol.Models.Danmaku.IWarningMessage; // summary broken up 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 6 | { 7 | /// 8 | /// 表示当前直播间被直播管理员警告消息的接口 9 | /// 10 | /// 11 | /// 消息来源是 Bilibili 直播平台 12 | /// 继承自以下接口: 13 | /// 14 | /// 15 | /// 16 | /// 17 | /// 18 | [RegisterBilibiliParser(typeof(WarningParser))] 19 | public interface IWarningMessage : ILiveManagementMessage, Executorlibs.Shared.Protocol.Models.Danmaku.IWarningMessage 20 | { 21 | 22 | } 23 | 24 | /// 25 | /// 表示一条当前直播间被直播管理员警告消息 26 | /// 27 | /// 28 | /// 消息来源是 Bilibili 直播平台 29 | /// 30 | public class WarningMessage : LiveManagementMessage, IWarningMessage 31 | { 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/WelcomeGuardMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using Executorlibs.Bilibili.Protocol.Models.Enums; 3 | using Executorlibs.Bilibili.Protocol.Parsers; 4 | using Executorlibs.Bilibili.Protocol.Parsers.Attributes; 5 | 6 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 7 | { 8 | /// 9 | /// 表示欢迎船员进入房间消息的接口 10 | /// 11 | /// 12 | /// 消息来源是 Bilibili 直播平台 13 | /// 继承自以下接口: 14 | /// 15 | /// 16 | /// 17 | /// 18 | /// 19 | [RegisterBilibiliParser(typeof(WelcomeGuardParser))] 20 | public interface IWelcomeGuardMessage : IUserMessage, IGuardMessage 21 | { 22 | 23 | } 24 | 25 | /// 26 | /// 表示欢迎船员进入房间消息 27 | /// 28 | /// 29 | /// 消息来源是 Bilibili 直播平台 30 | /// 31 | [DebuggerDisplay("{Time.ToString(\"u\")[..^1],nq} [WelcomeGuard] {UserName,nq}[{UserId}]")] 32 | public class WelcomeGuardMessage : UserMessage, IWelcomeGuardMessage 33 | { 34 | /// 35 | public GuardType GuardType { get; set; } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Danmaku/WelcomeMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using Executorlibs.Bilibili.Protocol.Models.Enums; 3 | using Executorlibs.Bilibili.Protocol.Parsers; 4 | using Executorlibs.Bilibili.Protocol.Parsers.Attributes; 5 | 6 | namespace Executorlibs.Bilibili.Protocol.Models.Danmaku 7 | { 8 | /// 9 | /// 表示欢迎老爷进入房间消息的接口 10 | /// 11 | /// 12 | /// 消息来源是 Bilibili 直播平台 13 | /// 继承自以下接口: 14 | /// 15 | /// 16 | /// 17 | /// 18 | /// 19 | /// 20 | [RegisterBilibiliParser(typeof(WelcomeParser))] 21 | public interface IWelcomeMessage : IUserMessage, ILordMessage, IAdminMessage 22 | { 23 | 24 | } 25 | 26 | /// 27 | /// 表示欢迎老爷进入房间消息 28 | /// 29 | /// 30 | /// 消息来源是 Bilibili 直播平台 31 | /// 32 | [DebuggerDisplay("{Time:yyyy-MM-dd HH:mm:ss} [Welcome] {UserName,nq}[{UserId}]")] 33 | public class WelcomeMessage : UserMessage, IWelcomeMessage 34 | { 35 | /// 36 | public LordType LordType { get; set; } 37 | 38 | /// 39 | public bool IsAdmin { get; set; } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/DanmakuServerInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.Bilibili.Protocol.Models 2 | { 3 | public class DanmakuServerInfo 4 | { 5 | public DanmakuServerHostInfo[] Hosts { get; } 6 | 7 | public string Token { get; } 8 | 9 | public DanmakuServerInfo(DanmakuServerHostInfo[] hosts, string token) 10 | { 11 | Hosts = hosts; 12 | Token = token; 13 | } 14 | } 15 | 16 | public struct DanmakuServerHostInfo 17 | { 18 | public string Host { get; set; } 19 | 20 | public int Port { get; set; } 21 | 22 | public int WsPort { get; set; } 23 | 24 | public int WssPort { get; set; } 25 | 26 | public DanmakuServerHostInfo(string host, int port, int wsPort, int wssPort) 27 | { 28 | Host = host; 29 | Port = port; 30 | WsPort = wsPort; 31 | WssPort = wssPort; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Enums/DanmakuMode.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.Bilibili.Protocol.Models.Enums 2 | { 3 | /// 4 | /// 表示弹幕模式 5 | /// 6 | public enum DanmakuMode 7 | { 8 | /// 9 | /// 未知弹幕 10 | /// 11 | Unknown = 0, 12 | /// 13 | /// 滚动弹幕 14 | /// 15 | Rolling = 1, 16 | /// 17 | /// 底端弹幕 18 | /// 19 | Bottom = 4, 20 | /// 21 | /// 顶端弹幕 22 | /// 23 | Top = 5, 24 | /// 25 | /// 反向弹幕 26 | /// 27 | Reverse = 6, 28 | /// 29 | /// 特殊弹幕 30 | /// 31 | Special = 7, 32 | /// 33 | /// 代码弹幕 34 | /// 35 | Code = 8, 36 | /// 37 | /// BAS弹幕 38 | /// 39 | BAS = 9 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Enums/GuardType.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.Bilibili.Protocol.Models.Enums 2 | { 3 | /// 4 | /// 表示船员类型 5 | /// 6 | public enum GuardType 7 | { 8 | /// 9 | /// 无 10 | /// 11 | None = 0, 12 | /// 13 | /// 总督 14 | /// 15 | Governor = 1, 16 | /// 17 | /// 提督 18 | /// 19 | Praefect = 2, 20 | /// 21 | /// 舰长 22 | /// 23 | Captain = 3, 24 | /// 25 | /// 周舰长 26 | /// 27 | WeekCaptain = 4, 28 | /// 29 | /// 总督v2 30 | /// 31 | Governorv2 = 5, 32 | /// 33 | /// 提督v2 34 | /// 35 | Praefectv2 = 6, 36 | /// 37 | /// 舰长v2 38 | /// 39 | Captainv2 = 7 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Enums/InteractType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Executorlibs.Bilibili.Protocol.Models.Enums 4 | { 5 | /// 6 | /// 互动消息类型 7 | /// 8 | [Flags] 9 | public enum InteractType 10 | { 11 | /// 12 | /// 进入直播间 13 | /// 14 | Enter = 1 << 0, 15 | /// 16 | /// 关注直播间 17 | /// 18 | Follow = 1 << 1, 19 | /// 20 | /// 分享直播间 21 | /// 22 | Share = 1 << 2, 23 | /// 24 | /// 特别关注直播间 25 | /// 26 | SpecialFollow = 1 << 3 | Follow, 27 | /// 28 | /// 互相关注 29 | /// 30 | MutualFollow = 1 << 4 | Follow 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Enums/InteractUserType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Executorlibs.Bilibili.Protocol.Models.Enums 4 | { 5 | /// 6 | /// 互动消息用户类型 7 | /// 8 | [Flags] 9 | public enum InteractUserType 10 | { 11 | /// 12 | /// 普通用户 13 | /// 14 | Normal = 1 << 0, 15 | /// 16 | /// 房间管理员 17 | /// 18 | Manager = 1 << 1, 19 | /// 20 | /// 粉丝团成员 21 | /// 22 | Fans = 1 << 2, 23 | /// 24 | /// 月费老爷 25 | /// 26 | Vip = 1 << 3, 27 | /// 28 | /// 年费老爷 29 | /// 30 | SVip = 1 << 4, 31 | /// 32 | /// 舰长 33 | /// 34 | Captain = 1 << 5, 35 | /// 36 | /// 提督 37 | /// 38 | Praefect = 1 << 6, 39 | /// 40 | /// 总督 41 | /// 42 | Governor = 1 << 7 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/Enums/LordType.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.Bilibili.Protocol.Models.Enums 2 | { 3 | /// 4 | /// 表示老爷类型 5 | /// 6 | public enum LordType 7 | { 8 | /// 9 | /// 不是老爷 10 | /// 11 | None, 12 | /// 13 | /// 月费老爷 14 | /// 15 | Monthly, 16 | /// 17 | /// 年费老爷 18 | /// 19 | Yearly 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/General/BilibiliMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using Executorlibs.MessageFramework.Models.General; 3 | using Executorlibs.Shared.Protocol.Models.General; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Models.General 6 | { 7 | /// 8 | /// 表示由B站发出的消息 9 | /// 10 | /// 11 | /// 继承自 12 | /// 13 | public interface IBilibiliMessage : IProtocolMessage 14 | { 15 | /// 16 | /// 房间号 17 | /// 18 | int RoomId { get; } 19 | } 20 | 21 | /// 22 | /// 实现 的抽象类 23 | /// 24 | public abstract class BilibiliMessage : ProtocolMessage, IBilibiliMessage 25 | { 26 | /// 27 | public int RoomId { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/General/ConnectedMessage.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Shared.Protocol.Models.General; 2 | using IGeneralConnectedMessage = Executorlibs.Shared.Protocol.Models.General.IConnectedMessage; 3 | 4 | namespace Executorlibs.Bilibili.Protocol.Models.General 5 | { 6 | public interface IConnectedMessage : IBilibiliMessage, IGeneralConnectedMessage 7 | { 8 | 9 | } 10 | 11 | public class ConnectedMessage : BilibiliMessage, IConnectedMessage 12 | { 13 | public ConnectReason Reason { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/General/DisconnectedMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using IGeneralDisconnectedMessage = Executorlibs.Shared.Protocol.Models.General.IDisconnectedMessage; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Models.General 6 | { 7 | public interface IDisconnectedMessage : IBilibiliMessage, IGeneralDisconnectedMessage 8 | { 9 | 10 | } 11 | 12 | public class DisconnectedMessage : BilibiliMessage, IDisconnectedMessage 13 | { 14 | public Exception? Exception { get; set; } 15 | 16 | public CancellationToken Token { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Models/General/UnknownMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.Bilibili.Protocol.Models.General 2 | { 3 | public interface IUnknownMessage : IBilibiliMessage 4 | { 5 | 6 | } 7 | 8 | public class UnknownMessage : BilibiliMessage, IUnknownMessage 9 | { 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Options/DanmakuClientOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Executorlibs.Bilibili.Protocol.Options 4 | { 5 | public class DanmakuClientOptions 6 | { 7 | public int RoomId { get; set; } 8 | 9 | public TimeSpan HeartbeatInterval { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/AnchorLotteryResultParser.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Bilibili.Protocol.Models.Danmaku; 2 | 3 | namespace Executorlibs.Bilibili.Protocol.Parsers 4 | { 5 | public class AnchorLotteryResultParser : CommonLotteryResultParser 6 | { 7 | private const string Command = "ANCHOR_LOT_AWARD"; 8 | 9 | /// 10 | public override string Key => Command; 11 | 12 | /// 13 | /// 初始化 类的新实例 14 | /// 15 | public AnchorLotteryResultParser() { } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/Attributes/RegisterBilibiliParserAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Executorlibs.MessageFramework.Parsers.Attributes; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Parsers.Attributes 6 | { 7 | 8 | /// 9 | /// 标记一个消息类、消息接口或者消息处理类所需要使用的 10 | /// 11 | public sealed class RegisterBilibiliParserAttribute : RegisterParserAttribute 12 | { 13 | /// 14 | /// 使用给定的 初始化 的新实例 15 | /// 16 | /// 的类型 17 | public RegisterBilibiliParserAttribute(Type implementationType) : this(implementationType, null) 18 | { 19 | 20 | } 21 | 22 | public RegisterBilibiliParserAttribute(Type implementationType, ServiceLifetime? lifetime) : base(implementationType, lifetime) 23 | { 24 | 25 | } 26 | 27 | protected override Type GetServiceType(Type implementationType) 28 | { 29 | Type openGeneric = typeof(IBilibiliMessageParser<>); 30 | foreach (Type interfaceType in implementationType.GetInterfaces()) 31 | { 32 | if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == openGeneric) 33 | { 34 | return typeof(IBilibiliMessageParser); 35 | } 36 | } 37 | throw new ArgumentException($"给定的 {implementationType.Name} 不实现 {openGeneric.Name}", nameof(implementationType)); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/BilibiliMappableMessageParser.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using System.Text.Json; 3 | using Executorlibs.Bilibili.Protocol.Models.General; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Parsers 6 | { 7 | /// 8 | /// 以 cmd 作为键的 9 | /// 10 | /// 11 | /// 仅供 Bilibili 直播平台的消息使用 12 | /// 13 | /// 14 | public abstract class BilibiliMappableMessageParser : BilibiliMessageParser, 15 | IMappableBilibiliMessageParser where TMessage : IBilibiliMessage 16 | { 17 | /// 18 | /// 表示弹幕数据中的 cmd 值 19 | /// 20 | public abstract string Key { get; } 21 | 22 | /// 23 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 24 | public override bool CanParse(in JsonElement root) 25 | { 26 | return root.TryGetProperty("cmd", out JsonElement commandToken) && commandToken.GetString() == Key; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/BilibiliMessageParser.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using Executorlibs.Bilibili.Protocol.Models.General; 3 | using Executorlibs.MessageFramework.Parsers; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Parsers 6 | { 7 | /// 8 | /// 表示处理B站消息的 9 | /// 10 | public interface IBilibiliMessageParser : IMessageParser 11 | { 12 | 13 | } 14 | 15 | /// 16 | /// 表示处理B站消息的 17 | /// 18 | /// 19 | public interface IBilibiliMessageParser : IBilibiliMessageParser, 20 | IMessageParser where TMessage : IBilibiliMessage 21 | { 22 | 23 | } 24 | 25 | public abstract class BilibiliMessageParser : MessageParser, IBilibiliMessageParser where TMessage : IBilibiliMessage 26 | { 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/CommonLotteryResultParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Text.Json; 4 | using Executorlibs.Bilibili.Protocol.Models.Danmaku; 5 | 6 | namespace Executorlibs.Bilibili.Protocol.Parsers 7 | { 8 | public abstract class CommonLotteryResultParser : BilibiliMappableMessageParser where TMessage : ICommonLotteryResultMessage 9 | where TImpl : CommonLotteryResultMessage, TMessage, new() 10 | { 11 | /// 12 | /// 初始化 类的新实例 13 | /// 14 | public CommonLotteryResultParser() { } 15 | 16 | /// 17 | /// 将给定的 处理为 实例 18 | /// 19 | /// 消息数据 20 | public override TMessage Parse(in JsonElement root) 21 | { 22 | JsonElement data = root.GetProperty("data"); 23 | return new TImpl 24 | { 25 | Id = data.GetProperty("id").GetInt32(), 26 | AwardName = data.GetProperty("award_name").GetString()!, 27 | AwardNum = data.GetProperty("award_num").GetInt32(), 28 | AwardUsers = data.GetProperty("award_users").EnumerateArray().Select(p => (p.GetProperty("uname").GetString()!, p.GetProperty("uid").GetInt64())).ToArray(), 29 | Time = DateTime.Now, 30 | Rawdata = root 31 | }; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/CutOffParser.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Bilibili.Protocol.Models.Danmaku; 2 | 3 | namespace Executorlibs.Bilibili.Protocol.Parsers 4 | { 5 | /// 6 | /// 处理当前直播间被直播管理员切断消息的 7 | /// 8 | public sealed class CutOffParser : CutOffParser 9 | { 10 | /// 11 | /// 初始化 类的新实例 12 | /// 13 | public CutOffParser() { } 14 | } 15 | 16 | public class CutOffParser : LiveManagementParser where TMessage : ICutOffMessage 17 | where TImpl : LiveManagementMessage, TMessage, new() 18 | { 19 | private const string Command = "CUT_OFF"; 20 | 21 | /// 22 | public override string Key => Command; 23 | 24 | /// 25 | /// 初始化 类的新实例 26 | /// 27 | public CutOffParser() { } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/DanmakuFallbackParser.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using Executorlibs.Bilibili.Protocol.Models.Danmaku; 3 | using Executorlibs.MessageFramework.Parsers.Attributes; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Parsers 6 | { 7 | /// 8 | /// 处理特殊时期普通弹幕的 9 | /// 10 | public sealed class DanmakuFallbackParser : DanmakuFallbackParser 11 | { 12 | 13 | } 14 | 15 | /// 16 | /// 处理特殊时期普通弹幕的 17 | /// 18 | [SuppressAutoMapping] 19 | public class DanmakuFallbackParser : DanmakuParser where TMessage : IDanmakuMessage 20 | where TImpl : DanmakuMessage, TMessage, new() 21 | { 22 | /// 23 | public override bool CanParse(in JsonElement root) 24 | { 25 | return root.TryGetProperty("cmd", out JsonElement commandToken) && (commandToken.GetString()?.StartsWith(Key) == true); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/DanmakuLotteryResultParser.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Bilibili.Protocol.Models.Danmaku; 2 | 3 | namespace Executorlibs.Bilibili.Protocol.Parsers 4 | { 5 | public class DanmakuLotteryResultParser : CommonLotteryResultParser 6 | { 7 | private const string Command = "DANMU_GIFT_LOTTERY_AWARD"; 8 | 9 | /// 10 | public override string Key => Command; 11 | 12 | /// 13 | /// 初始化 类的新实例 14 | /// 15 | public DanmakuLotteryResultParser() { } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/EnterParser.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using System.Text.Json; 3 | using Executorlibs.Bilibili.Protocol.Models.Danmaku; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Parsers 6 | { 7 | /// 8 | /// 处理用户进入直播间消息的 9 | /// 10 | public sealed class EnterParser : EnterParser 11 | { 12 | 13 | } 14 | 15 | /// 16 | /// 处理用户进入直播间消息的 17 | /// 18 | public class EnterParser : InteractBaseParser where TMessage : IEnterMessage 19 | where TImpl : EnterMessage, TMessage, new() 20 | { 21 | /// 22 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 23 | public override bool CanParse(in JsonElement root) 24 | { 25 | return base.CanParse(in root) && 26 | root.TryGetProperty("data", out JsonElement data) && 27 | data.TryGetProperty("msg_type", out JsonElement msgType) && 28 | msgType.TryGetInt32(out int value) && 29 | value == 1; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/FollowParser.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using System.Text.Json; 3 | using Executorlibs.Bilibili.Protocol.Models.Danmaku; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Parsers 6 | { 7 | /// 8 | /// 处理用户关注直播间消息的 9 | /// 10 | public sealed class FollowParser : InteractBaseParser 11 | { 12 | /// 13 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 14 | public override bool CanParse(in JsonElement root) 15 | { 16 | return base.CanParse(in root) && 17 | root.TryGetProperty("data", out JsonElement data) && 18 | data.TryGetProperty("msg_type", out JsonElement msgType) && 19 | msgType.TryGetInt32(out int value) && 20 | value == 2; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/IMappableBilibiliMessageParser.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using Executorlibs.Bilibili.Protocol.Models.General; 3 | using Executorlibs.MessageFramework.Parsers; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Parsers 6 | { 7 | /// 8 | /// 以 作为键的 9 | /// 10 | public interface IMappableBilibiliMessageParser : IMappableMessageParser, IBilibiliMessageParser 11 | { 12 | 13 | } 14 | 15 | /// 16 | /// 以 作为键的 17 | /// 18 | /// 19 | public interface IMappableBilibiliMessageParser : IMappableMessageParser, 20 | IBilibiliMessageParser, 21 | IMappableBilibiliMessageParser where TMessage : IBilibiliMessage 22 | { 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/InteractParser.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using System.Text.Json; 3 | using Executorlibs.Bilibili.Protocol.Models.Danmaku; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Parsers 6 | { 7 | /// 8 | /// 处理用户互动消息的 9 | /// 10 | public sealed class InteractParser : InteractBaseParser, IMappableBilibiliMessageParser 11 | { 12 | /// 13 | /// 本方法始终返回 14 | /// 15 | /// 16 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 17 | public override bool CanParse(in JsonElement root) 18 | { 19 | return true; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/LiveEndParser.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Bilibili.Protocol.Models.Danmaku; 2 | 3 | namespace Executorlibs.Bilibili.Protocol.Parsers 4 | { 5 | /// 6 | /// 处理主播下播消息的 7 | /// 8 | public class LiveEndParser : SimpleBilibiliMessageParser 9 | { 10 | private const string Command = "PREPARING"; 11 | 12 | /// 13 | public override string Key => Command; 14 | 15 | /// 16 | /// 初始化 类的新实例 17 | /// 18 | public LiveEndParser() { } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/LiveManagementParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json; 3 | using Executorlibs.Bilibili.Protocol.Models.Danmaku; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Parsers 6 | { 7 | public abstract class LiveManagementParser : BilibiliMappableMessageParser where TMessage : ILiveManagementMessage 8 | where TImpl : LiveManagementMessage, TMessage, new() 9 | { 10 | /// 11 | /// 将给定的 处理为 实例 12 | /// 13 | /// 消息数据 14 | public override TMessage Parse(in JsonElement root) 15 | { 16 | return new TImpl 17 | { 18 | Message = root.TryGetProperty("msg", out JsonElement msgToken) ? msgToken.GetString() : null, 19 | Time = DateTime.Now, 20 | Rawdata = root 21 | }; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/OnlineCountParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json; 3 | using Executorlibs.Bilibili.Protocol.Models.Danmaku; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Parsers 6 | { 7 | public class OnlineCountParser : OnlineCountParser 8 | { 9 | /// 10 | /// 初始化 类的新实例 11 | /// 12 | public OnlineCountParser() { } 13 | } 14 | 15 | public class OnlineCountParser : BilibiliMappableMessageParser where TMessage : IOnlineCountMessage 16 | where TImpl : OnlineCountMessage, TMessage, new() 17 | { 18 | private const string Command = "ONLINE_RANK_COUNT"; 19 | 20 | /// 21 | public override string Key => Command; 22 | 23 | /// 24 | /// 初始化 类的新实例 25 | /// 26 | public OnlineCountParser() { } 27 | 28 | /// 29 | /// 将给定的 处理为 实例 30 | /// 31 | /// 消息数据 32 | public override TMessage Parse(in JsonElement root) 33 | { 34 | JsonElement data = root.GetProperty("data"); 35 | TImpl message = new TImpl(); 36 | message.Count = data.GetProperty("count").GetInt32(); 37 | message.Rawdata = root; 38 | message.Time = DateTime.Now; 39 | return message; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/PkBaseParser.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using Executorlibs.Bilibili.Protocol.Models.Danmaku; 3 | using Executorlibs.Shared; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Parsers 6 | { 7 | public abstract class PkBaseParser : BilibiliMappableMessageParser where TMessage : IPkBaseMessage 8 | where TImpl : PkBaseMessage, TMessage, new() 9 | { 10 | /// 11 | /// 将给定的 处理为 实例 12 | /// 13 | /// 消息数据 14 | public override TMessage Parse(in JsonElement root) 15 | { 16 | TImpl message = new TImpl(); 17 | JsonElement idToken = root.GetProperty("pk_id"); 18 | message.Id = idToken.ValueKind == JsonValueKind.Number ? idToken.GetInt32() : int.Parse(idToken.GetString()!); // 该死的后端真的该鲨了祭天 19 | message.Time = Utils.UnixTime2DateTime(root.GetProperty("timestamp").GetInt32()); 20 | return message; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/PkStartParser.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using Executorlibs.Bilibili.Protocol.Models.Danmaku; 3 | using Executorlibs.Shared; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Parsers 6 | { 7 | public class PkStartParser : PkStartParser 8 | { 9 | /// 10 | /// 初始化 类的新实例 11 | /// 12 | public PkStartParser() { } 13 | } 14 | 15 | public class PkStartParser : PkBaseParser where TMessage : IPkStartMessage 16 | where TImpl : PkStartMessage, TMessage, new() 17 | { 18 | private const string Command = "PK_BATTLE_START"; 19 | 20 | /// 21 | public override string Key => Command; 22 | 23 | /// 24 | /// 初始化 类的新实例 25 | /// 26 | public PkStartParser() { } 27 | 28 | /// 29 | public override TMessage Parse(in JsonElement root) 30 | { 31 | TImpl message = (TImpl)base.Parse(root); 32 | message.EndTime = Utils.UnixTime2DateTime(root.GetProperty("data").GetProperty("pk_end_time").GetInt32()); 33 | return message; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/RoomLockParser.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Bilibili.Protocol.Models.Danmaku; 2 | 3 | namespace Executorlibs.Bilibili.Protocol.Parsers 4 | { 5 | /// 6 | /// 处理当前直播间被直播管理员关闭消息的 7 | /// 8 | public sealed class RoomLockParser : RoomLockParser 9 | { 10 | /// 11 | /// 初始化 类的新实例 12 | /// 13 | public RoomLockParser() { } 14 | } 15 | 16 | public class RoomLockParser : LiveManagementParser where TMessage : IRoomLockMessage 17 | where TImpl : LiveManagementMessage, TMessage, new() 18 | { 19 | private const string Command = "ROOM_LOCK"; 20 | 21 | /// 22 | public override string Key => Command; 23 | 24 | /// 25 | /// 初始化 类的新实例 26 | /// 27 | public RoomLockParser() { } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/SimpleBilibiliMessageParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json; 3 | using Executorlibs.Bilibili.Protocol.Models.General; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Parsers 6 | { 7 | /// 8 | /// 处理简单B站消息的 9 | /// 10 | /// 11 | /// 12 | public abstract class SimpleBilibiliMessageParser : BilibiliMappableMessageParser where TInterface : IBilibiliMessage 13 | where TImplementation : BilibiliMessage, TInterface, new() 14 | { 15 | /// 16 | /// 将给定的 处理为 实例 17 | /// 18 | /// 消息数据 19 | public override TInterface Parse(in JsonElement root) 20 | { 21 | return new TImplementation 22 | { 23 | Time = DateTime.Now, 24 | Rawdata = root 25 | }; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/UnknownMessageParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json; 3 | using Executorlibs.Bilibili.Protocol.Models.General; 4 | 5 | namespace Executorlibs.Bilibili.Protocol.Parsers 6 | { 7 | public interface IUnknownMessageParser : IBilibiliMessageParser 8 | { 9 | 10 | } 11 | 12 | /// 13 | /// 处理未知消息的 14 | /// 15 | public sealed class UnknownMessageParser : UnknownMessageParser 16 | { 17 | /// 18 | /// 初始化 类的新实例 19 | /// 20 | public UnknownMessageParser() 21 | { 22 | 23 | } 24 | } 25 | 26 | /// 27 | /// 处理未知消息的 28 | /// 29 | public class UnknownMessageParser : BilibiliMessageParser, IUnknownMessageParser where TImpl : UnknownMessage, IUnknownMessage, new() 30 | { 31 | /// 32 | /// 初始化 类的新实例 33 | /// 34 | public UnknownMessageParser() 35 | { 36 | 37 | } 38 | 39 | public override bool CanParse(in JsonElement root) 40 | { 41 | return true; 42 | } 43 | 44 | public override IUnknownMessage Parse(in JsonElement root) 45 | { 46 | return new TImpl() { Rawdata = root, Time = DateTime.Now }; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/WarningParser.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Bilibili.Protocol.Models.Danmaku; 2 | 3 | namespace Executorlibs.Bilibili.Protocol.Parsers 4 | { 5 | /// 6 | /// 处理当前直播间被直播管理员警告消息的 7 | /// 8 | public sealed class WarningParser : WarningParser 9 | { 10 | /// 11 | /// 初始化 类的新实例 12 | /// 13 | public WarningParser() { } 14 | } 15 | 16 | public class WarningParser : LiveManagementParser where TMessage : IWarningMessage 17 | where TImpl : LiveManagementMessage, TMessage, new() 18 | { 19 | private const string Command = "WARNING"; 20 | 21 | /// 22 | public override string Key => Command; 23 | 24 | /// 25 | /// 初始化 类的新实例 26 | /// 27 | public WarningParser() { } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Executorlibs.Bilibili.Protocol/Parsers/WelcomeGuardParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json; 3 | using Executorlibs.Bilibili.Protocol.Models.Danmaku; 4 | using Executorlibs.Bilibili.Protocol.Models.Enums; 5 | 6 | namespace Executorlibs.Bilibili.Protocol.Parsers 7 | { 8 | /// 9 | /// 处理欢迎船员进入房间消息的 10 | /// 11 | public class WelcomeGuardParser : BilibiliMappableMessageParser 12 | { 13 | private const string Command = "WELCOME_GUARD"; 14 | 15 | /// 16 | public override string Key => Command; 17 | 18 | /// 19 | /// 初始化 类的新实例 20 | /// 21 | public WelcomeGuardParser() { } 22 | 23 | /// 24 | /// 将给定的 处理为 实例 25 | /// 26 | /// 消息数据 27 | public override IWelcomeGuardMessage Parse(in JsonElement root) 28 | { 29 | JsonElement data = root.GetProperty("data"); 30 | return new WelcomeGuardMessage 31 | { 32 | UserName = data.GetProperty("username").GetString()!, 33 | UserId = data.GetProperty("uid").GetInt64(), 34 | GuardType = (GuardType)data.GetProperty("guard_level").GetInt32(), 35 | Time = DateTime.Now, 36 | Rawdata = root 37 | }; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Executorlibs.Caching/Abstractions/IMemoryCache.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Microsoft.Extensions.Caching.Memory 4 | { 5 | /// 6 | /// Represents a local in-memory cache whose values are not serialized. 7 | /// 8 | public interface IMemoryCache : IDisposable where TKey : notnull 9 | { 10 | /// 11 | /// Gets the item associated with this key if present. 12 | /// 13 | /// An object identifying the requested entry. 14 | /// The located value or null. 15 | /// True if the key was found. 16 | bool TryGetValue(TKey key, out TValue? value); 17 | 18 | /// 19 | /// Create or overwrite an entry in the cache. 20 | /// 21 | /// An object identifying the entry. 22 | /// The newly created instance. 23 | ICacheEntry CreateEntry(TKey key); 24 | 25 | /// 26 | /// Removes the object associated with the given key. 27 | /// 28 | /// An object identifying the entry. 29 | void Remove(TKey key); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Executorlibs.Caching/CacheEntryHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | 3 | namespace Microsoft.Extensions.Caching.Memory 4 | { 5 | internal static class CacheEntryHelper where TKey : notnull 6 | { 7 | private static readonly AsyncLocal> _current = new AsyncLocal>(); 8 | 9 | internal static CacheEntry Current 10 | { 11 | get => _current.Value!; 12 | private set => _current.Value = value; 13 | } 14 | 15 | internal static CacheEntry EnterScope(CacheEntry current) 16 | { 17 | CacheEntry previous = Current; 18 | Current = current; 19 | return previous; 20 | } 21 | 22 | internal static void ExitScope(CacheEntry current, CacheEntry previous) 23 | { 24 | Current = previous; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Executorlibs.Caching/Executorlibs.Caching.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/Executorlibs.Caching/MemoryCacheOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.Extensions.Caching.Memory 2 | { 3 | public class MemoryCacheOptions : MemoryCacheOptions where TKey : notnull 4 | { 5 | 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/Executorlibs.Caching/PostEvictionCallbackRegistration.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.Extensions.Caching.Memory 2 | { 3 | public class PostEvictionCallbackRegistration where TKey : notnull 4 | { 5 | public PostEvictionDelegate EvictionCallback { get; set; } = null!; 6 | 7 | public object? State { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Executorlibs.Caching/PostEvictionDelegate.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.Extensions.Caching.Memory 2 | { 3 | /// 4 | /// Signature of the callback which gets called when a cache entry expires. 5 | /// 6 | /// The key of the entry being evicted. 7 | /// The value of the entry being evicted. 8 | /// The . 9 | /// The information that was passed when registering the callback. 10 | public delegate void PostEvictionDelegate(TKey key, TValue? value, EvictionReason reason, object? state) where TKey : notnull; 11 | } 12 | -------------------------------------------------------------------------------- /src/Executorlibs.Examples/Executorlibs.Examples.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | net6.0 6 | net6.0 7 | 8 | 9 | 10 | 12 | 13 | Exe 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop.NativeAssets.Win32/Executorlibs.FFmpegInterop.NativeAssets.Win32.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | True 5 | 6 | 7 | 8 | <_NativeFFmpegFile Include="$(MSBuildThisFileDirectory)..\..\runtimes\win-x64\native\*.dll" Dir="x64\"/> 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop.NativeAssets.Win32/_._: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Executor-Cheng/Executorlibs/77e80b0ca34519093af594858b1d9245ce5e1ff6/src/Executorlibs.FFmpegInterop.NativeAssets.Win32/_._ -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop.NativeAssets.Win32/runtimes/win-x64/native/avcodec-59.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Executor-Cheng/Executorlibs/77e80b0ca34519093af594858b1d9245ce5e1ff6/src/Executorlibs.FFmpegInterop.NativeAssets.Win32/runtimes/win-x64/native/avcodec-59.dll -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop.NativeAssets.Win32/runtimes/win-x64/native/avdevice-59.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Executor-Cheng/Executorlibs/77e80b0ca34519093af594858b1d9245ce5e1ff6/src/Executorlibs.FFmpegInterop.NativeAssets.Win32/runtimes/win-x64/native/avdevice-59.dll -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop.NativeAssets.Win32/runtimes/win-x64/native/avfilter-8.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Executor-Cheng/Executorlibs/77e80b0ca34519093af594858b1d9245ce5e1ff6/src/Executorlibs.FFmpegInterop.NativeAssets.Win32/runtimes/win-x64/native/avfilter-8.dll -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop.NativeAssets.Win32/runtimes/win-x64/native/avformat-59.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Executor-Cheng/Executorlibs/77e80b0ca34519093af594858b1d9245ce5e1ff6/src/Executorlibs.FFmpegInterop.NativeAssets.Win32/runtimes/win-x64/native/avformat-59.dll -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop.NativeAssets.Win32/runtimes/win-x64/native/avutil-57.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Executor-Cheng/Executorlibs/77e80b0ca34519093af594858b1d9245ce5e1ff6/src/Executorlibs.FFmpegInterop.NativeAssets.Win32/runtimes/win-x64/native/avutil-57.dll -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop.NativeAssets.Win32/runtimes/win-x64/native/postproc-56.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Executor-Cheng/Executorlibs/77e80b0ca34519093af594858b1d9245ce5e1ff6/src/Executorlibs.FFmpegInterop.NativeAssets.Win32/runtimes/win-x64/native/postproc-56.dll -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop.NativeAssets.Win32/runtimes/win-x64/native/swresample-4.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Executor-Cheng/Executorlibs/77e80b0ca34519093af594858b1d9245ce5e1ff6/src/Executorlibs.FFmpegInterop.NativeAssets.Win32/runtimes/win-x64/native/swresample-4.dll -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop.NativeAssets.Win32/runtimes/win-x64/native/swscale-6.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Executor-Cheng/Executorlibs/77e80b0ca34519093af594858b1d9245ce5e1ff6/src/Executorlibs.FFmpegInterop.NativeAssets.Win32/runtimes/win-x64/native/swscale-6.dll -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop/Executorlibs.FFmpegInterop.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop/Models/AVCodec.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace Executorlibs.FFmpegInterop.Models 4 | { 5 | [StructLayout(LayoutKind.Explicit)] 6 | public unsafe struct AVCodec 7 | { 8 | [FieldOffset(0)] 9 | private fixed byte _data[224]; 10 | 11 | [FieldOffset(20)] 12 | public int Id; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop/Models/AVCodecContext.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace Executorlibs.FFmpegInterop.Models 4 | { 5 | [StructLayout(LayoutKind.Explicit)] 6 | public unsafe struct AVCodecContext 7 | { 8 | [FieldOffset(0)] 9 | private fixed byte _data[920]; 10 | 11 | [FieldOffset(56)] 12 | public long Bitrate; 13 | 14 | [FieldOffset(352)] 15 | public int SampleRate; 16 | 17 | [FieldOffset(356)] 18 | public int Channels; 19 | 20 | [FieldOffset(360)] 21 | public AVSampleFormat SampleFormat; 22 | 23 | [FieldOffset(384)] 24 | public ulong ChannelLayout; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop/Models/AVCodecParameters.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace Executorlibs.FFmpegInterop.Models 4 | { 5 | [StructLayout(LayoutKind.Explicit)] 6 | public unsafe struct AVCodecParameters 7 | { 8 | [FieldOffset(0)] 9 | private fixed byte _data[144]; 10 | 11 | [FieldOffset(0)] 12 | public int CodecType; 13 | 14 | [FieldOffset(4)] 15 | public int CodecId; 16 | 17 | [FieldOffset(28)] 18 | public AVSampleFormat Format; 19 | 20 | [FieldOffset(32)] 21 | public long Bitrate; 22 | 23 | [FieldOffset(104)] 24 | public ulong ChannelLayout; 25 | 26 | [FieldOffset(112)] 27 | public int Channels; 28 | 29 | [FieldOffset(116)] 30 | public int SampleRate; 31 | 32 | [FieldOffset(124)] 33 | public int FrameSize; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop/Models/AVDictionary.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.FFmpegInterop.Models 2 | { 3 | public unsafe struct AVDictionary 4 | { 5 | public int Count; 6 | 7 | public void* Entries; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop/Models/AVFormatContext.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace Executorlibs.FFmpegInterop.Models 4 | { 5 | [StructLayout(LayoutKind.Explicit)] 6 | public unsafe struct AVFormatContext 7 | { 8 | [FieldOffset(0)] 9 | private fixed byte _data[472]; 10 | 11 | [FieldOffset(32)] 12 | public AVIOContext* Pb; 13 | 14 | [FieldOffset(44)] 15 | public int StreamCount; 16 | 17 | [FieldOffset(48)] 18 | public AVStream** Streams; 19 | 20 | [FieldOffset(64)] 21 | public long StartTime; 22 | 23 | [FieldOffset(72)] 24 | public long Duration; 25 | 26 | [FieldOffset(80)] 27 | public long Bitrate; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop/Models/AVFrame.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace Executorlibs.FFmpegInterop.Models 4 | { 5 | [StructLayout(LayoutKind.Explicit)] 6 | public unsafe struct AVFrame 7 | { 8 | [FieldOffset(0)] 9 | private fixed byte _data[448]; 10 | 11 | [FieldOffset(0)] 12 | public fixed long Data[8]; 13 | //#if TARGET_64BIT 14 | // public fixed long Data[8]; 15 | //#else 16 | // public fixed int Data[8]; 17 | //#endif 18 | 19 | [FieldOffset(64)] 20 | public fixed int Linesize[8]; 21 | 22 | [FieldOffset(96)] 23 | public byte** ExtendedData; 24 | 25 | [FieldOffset(112)] 26 | public int SampleCount; 27 | 28 | [FieldOffset(116)] 29 | public AVSampleFormat Format; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop/Models/AVIOContext.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace Executorlibs.FFmpegInterop.Models 4 | { 5 | [StructLayout(LayoutKind.Explicit)] 6 | public unsafe struct AVIOContext 7 | { 8 | [FieldOffset(0)] 9 | private fixed byte _data[208]; 10 | 11 | [FieldOffset(8)] 12 | public byte* Buffer; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop/Models/AVInputFormat.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace Executorlibs.FFmpegInterop.Models 4 | { 5 | [StructLayout(LayoutKind.Explicit)] 6 | public unsafe struct AVInputFormat 7 | { 8 | [FieldOffset(0)] 9 | private fixed byte _data[152]; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop/Models/AVMediaType.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.FFmpegInterop.Models 2 | { 3 | public enum AVMediaType 4 | { 5 | Unknown = -1, 6 | 7 | Video, 8 | 9 | Audio, 10 | 11 | Data, 12 | 13 | Subtitle, 14 | 15 | Attachment, 16 | 17 | Number 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop/Models/AVPacket.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace Executorlibs.FFmpegInterop.Models 4 | { 5 | [StructLayout(LayoutKind.Explicit)] 6 | public unsafe struct AVPacket 7 | { 8 | [FieldOffset(0)] 9 | private fixed byte _data[104]; 10 | 11 | [FieldOffset(24)] 12 | public byte* Data; 13 | 14 | [FieldOffset(32)] 15 | public int Size; 16 | 17 | [FieldOffset(36)] 18 | public int StreamIndex; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop/Models/AVSampleFormat.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.FFmpegInterop.Models 2 | { 3 | public enum AVSampleFormat 4 | { 5 | AV_SAMPLE_FMT_S16 = 1, 6 | 7 | AV_SAMPLE_FMT_FLTP = 8 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop/Models/AVSeek.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.FFmpegInterop.Models 2 | { 3 | public enum AVSeek 4 | { 5 | Begin = 0, 6 | 7 | Current = 1, 8 | 9 | End = 2, 10 | 11 | Size = 0x10000 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop/Models/AVStream.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace Executorlibs.FFmpegInterop.Models 4 | { 5 | [StructLayout(LayoutKind.Explicit)] 6 | public unsafe struct AVStream 7 | { 8 | [FieldOffset(0)] 9 | private fixed byte _data[224]; 10 | 11 | [FieldOffset(0)] 12 | public int Index; 13 | 14 | [FieldOffset(24)] 15 | public long StartTime; 16 | 17 | [FieldOffset(32)] 18 | public long Duration; 19 | 20 | [FieldOffset(40)] 21 | public long FrameCount; 22 | 23 | [FieldOffset(208)] 24 | public AVCodecParameters* CodecParameters; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Executorlibs.FFmpegInterop/SwresampleNativeMethods.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using Executorlibs.FFmpegInterop.Models; 3 | 4 | #pragma warning disable CA1401 // P/Invokes should not be visible 5 | namespace Executorlibs.FFmpegInterop 6 | { 7 | public static unsafe class SwresampleNativeMethods 8 | { 9 | [DllImport("swresample-4.dll", EntryPoint = "swr_alloc", CallingConvention = CallingConvention.StdCall)] 10 | public static extern void* AllocContext(); 11 | 12 | [DllImport("swresample-4.dll", EntryPoint = "swr_alloc_set_opts", CallingConvention = CallingConvention.StdCall)] 13 | public static extern void* AllocSetOptions(void* s, ulong outChannelLayout, AVSampleFormat outSampleFormat, int outSampleRate, 14 | ulong inChannelLayout, AVSampleFormat inSampleFormat, int inSampleRate, 15 | int logOffset, void* logContext); 16 | 17 | [DllImport("swresample-4.dll", EntryPoint = "swr_init", CallingConvention = CallingConvention.StdCall)] 18 | public static extern int InitContext(void* s); 19 | 20 | [DllImport("swresample-4.dll", EntryPoint = "swr_free", CallingConvention = CallingConvention.StdCall)] 21 | public static extern void FreeContext(void** s); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Executorlibs.Huya.Protocol/Clients/HuyaClientBase.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using Executorlibs.Huya.Protocol.Invokers; 3 | using Executorlibs.Huya.Protocol.Options; 4 | using Microsoft.Extensions.Options; 5 | 6 | namespace Executorlibs.Huya.Protocol.Clients 7 | { 8 | public abstract class HuyaClientBase 9 | { 10 | protected CancellationTokenSource? _cts = new(); 11 | 12 | protected CancellationTokenSource? _workerCts; 13 | 14 | protected IHuyaMessageHandlerInvoker _invoker; 15 | 16 | protected IHuyaMessageSubscriptionResolver _resolver; 17 | 18 | protected HuyaClientOptions _options; 19 | 20 | protected HuyaClientBase(IHuyaMessageHandlerInvoker invoker, IHuyaMessageSubscriptionResolver resolver, IOptionsSnapshot options) 21 | { 22 | _invoker = invoker; 23 | _resolver = resolver; 24 | _options = options.Value; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Executorlibs.Huya.Protocol/Clients/IHuyaClient.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Shared.Protocol.Clients; 2 | 3 | namespace Executorlibs.Huya.Protocol.Clients 4 | { 5 | public interface IHuyaClient : IProtocolClient 6 | { 7 | long RoomId { get; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Executorlibs.Huya.Protocol/Executorlibs.Huya.Protocol.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0;net5.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/Executorlibs.Huya.Protocol/Handlers/IContravarianceHuyaMessageHandler.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Huya.Protocol.Clients; 2 | using Executorlibs.Huya.Protocol.Models.General; 3 | using Executorlibs.MessageFramework.Handlers; 4 | 5 | namespace Executorlibs.Huya.Protocol.Handlers 6 | { 7 | public interface IContravarianceHuyaMessageHandler : IHuyaMessageHandler, IContravarianceMessageHandler where TMessage : IHuyaMessage 8 | { 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Executorlibs.Huya.Protocol/Handlers/IInvarianceHuyaMessageHandler.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Huya.Protocol.Clients; 2 | using Executorlibs.Huya.Protocol.Models.General; 3 | using Executorlibs.MessageFramework.Handlers; 4 | 5 | namespace Executorlibs.Huya.Protocol.Handlers 6 | { 7 | public interface IInvarianceHuyaMessageHandler : IHuyaMessageHandler, IInvarianceMessageHandler where TMessage : IHuyaMessage 8 | { 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Executorlibs.Huya.Protocol/Invokers/Attributes/RegisterHuyaMessageSubscriptionResolverAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Executorlibs.MessageFramework.Invoking.Attributes; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Executorlibs.Huya.Protocol.Invokers.Attributes 6 | { 7 | public class RegisterHuyaMessageSubscriptionResolverAttribute : RegisterMessageSubscriptionResolverAttribute 8 | { 9 | public RegisterHuyaMessageSubscriptionResolverAttribute(Type implementationType) : this(implementationType, null) 10 | { 11 | 12 | } 13 | 14 | public RegisterHuyaMessageSubscriptionResolverAttribute(Type implementationType, ServiceLifetime? lifetime) : base(implementationType, lifetime) 15 | { 16 | 17 | } 18 | 19 | protected override Type GetServiceType(Type implementationType) 20 | { 21 | var interfaceType = typeof(IHuyaMessageSubscriptionResolver); 22 | if (interfaceType.IsAssignableFrom(implementationType)) 23 | { 24 | return interfaceType; 25 | } 26 | throw new ArgumentException($"给定的 {implementationType.Name} 不实现 {interfaceType.Name}", nameof(implementationType)); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Executorlibs.Huya.Protocol/Invokers/IHuyaMessageSubscription.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Executorlibs.Huya.Protocol.Clients; 3 | using Executorlibs.Huya.Protocol.Handlers; 4 | using Executorlibs.Huya.Protocol.Models.General; 5 | using Executorlibs.MessageFramework.Invoking; 6 | 7 | namespace Executorlibs.Huya.Protocol.Invokers 8 | { 9 | public interface IHuyaMessageSubscription : IMessageSubscription, IHuyaMessageHandler 10 | { 11 | 12 | } 13 | 14 | public interface IHuyaMessageSubscription : IHuyaMessageSubscription, IHuyaMessageHandler where TMessage : IHuyaMessage 15 | { 16 | #if !NETSTANDARD2_0 17 | Task IHuyaMessageHandler.HandleMessageAsync(IHuyaClient client, IHuyaMessage message) 18 | => HandleMessageAsync(client, (TMessage)message); 19 | #endif 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Executorlibs.Huya.Protocol/Models/General/HuyaMessage.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.MessageFramework.Models.General; 2 | using Executorlibs.Shared.Protocol.Models.General; 3 | 4 | namespace Executorlibs.Huya.Protocol.Models.General 5 | { 6 | /// 7 | /// 表示由B站发出的消息 8 | /// 9 | /// 10 | /// 继承自 11 | /// 12 | public interface IHuyaMessage : IProtocolMessage 13 | { 14 | /// 15 | /// 房间号 16 | /// 17 | long RoomId { get; } 18 | } 19 | 20 | /// 21 | /// 实现 的抽象类 22 | /// 23 | public abstract class HuyaMessage : ProtocolMessage, IHuyaMessage 24 | { 25 | /// 26 | public long RoomId { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Executorlibs.Huya.Protocol/Models/General/UnknownMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.Huya.Protocol.Models.General 2 | { 3 | public interface IUnknownMessage : IHuyaMessage 4 | { 5 | 6 | } 7 | 8 | public class UnknownMessage : HuyaMessage 9 | { 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Executorlibs.Huya.Protocol/Models/HuyaMsgType.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.Huya.Protocol.Models 2 | { 3 | public enum HuyaMsgType : byte 4 | { 5 | Null = 0, 6 | RegisterRequest = 1, 7 | RegisterResponse = 2, 8 | WupRequest = 3, 9 | WupResponse = 4, 10 | HeartBeat = 5, 11 | HeartBeatAck = 6, 12 | MsgPushRequest = 7, 13 | DeregisterRequest = 8, 14 | DeRegisterResponse = 9, 15 | VerifyCookieRequest = 10, 16 | VerifyCookieResponse = 11, 17 | VerifyHuyaTokenRequest = 12, 18 | VerifyHuyaTokenResponse = 13, 19 | UnVerifyRequest = 14, 20 | UnVerifyResponse = 15, 21 | RegisterGroupRequest = 16, 22 | RegisterGroupResponse = 17, 23 | UnRegisterGroupRequest = 18, 24 | UnRegisterGroupResponse = 19, 25 | HeartBeatRequest = 20, 26 | HeartBeatResponse = 21, 27 | MsgPushRequestv2 = 22, 28 | UpdateUserExpsRequest = 23, 29 | UpdateUserExpsResponse = 24, 30 | WsHistoryMsgRequest = 25, 31 | WSHistoryMsgResponse = 26, 32 | EnterP2P = 27, 33 | EnterP2PAck = 28, 34 | ExitP2P = 29, 35 | ExitP2PAck = 30, 36 | SyncGroupRequest = 31, 37 | SyncGroupResponse = 32, 38 | UpdateUserInfoRequest = 33, 39 | UpdateUserInfoResponse = 34, 40 | MsgAckRequest = 35, 41 | MsgAckResponse = 36, 42 | CloudGameRequest = 37, 43 | CloudGamePush = 38, 44 | CloudGameResponse = 39 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Executorlibs.Huya.Protocol/Models/MessageSenderInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Executorlibs.TarProtocol.IO; 3 | using Executorlibs.TarProtocol.Models; 4 | using Executorlibs.TarProtocol.Models.Primitives; 5 | 6 | namespace Executorlibs.Huya.Protocol.Models 7 | { 8 | public class MessageSenderInfo : ITarType // SenderInfo 9 | { 10 | public long UserId; 11 | 12 | public long IMid; 13 | 14 | public string UserName = null!; 15 | 16 | public int Gender; 17 | 18 | public string AvartarUrl = null!; 19 | 20 | public int NobleLevel; 21 | 22 | public NobleLevelInfo NobleLevelInfo = null!; 23 | 24 | public string Guid = null!; 25 | 26 | public string UserAgent = null!; 27 | 28 | public void ReadFrom(ref TarReader reader) 29 | { 30 | UserId = reader.Read(); 31 | IMid = reader.Read(); 32 | UserName = reader.Read(); 33 | Gender = reader.Read(); 34 | AvartarUrl = reader.Read(); 35 | NobleLevel = reader.Read(); 36 | NobleLevelInfo = reader.Read>(); 37 | Guid = reader.Read(); 38 | UserAgent = reader.Read(); 39 | } 40 | 41 | public void WriteTo(ref TarWriter writer) 42 | { 43 | throw new NotSupportedException(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Executorlibs.Huya.Protocol/Models/NobleLevelInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Executorlibs.TarProtocol.IO; 3 | using Executorlibs.TarProtocol.Models; 4 | using Executorlibs.TarProtocol.Models.Primitives; 5 | 6 | namespace Executorlibs.Huya.Protocol.Models 7 | { 8 | public class NobleLevelInfo : ITarType // NobleLevelInfo 9 | { 10 | public int Level; 11 | 12 | public int AttributeType; 13 | 14 | public void ReadFrom(ref TarReader reader) 15 | { 16 | Level = reader.Read(); 17 | AttributeType = reader.Read(); 18 | } 19 | 20 | public void WriteTo(ref TarWriter writer) 21 | { 22 | throw new NotSupportedException(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Executorlibs.Huya.Protocol/Models/PerSuffixInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Executorlibs.TarProtocol.IO; 3 | using Executorlibs.TarProtocol.Models; 4 | using Executorlibs.TarProtocol.Models.Primitives; 5 | 6 | namespace Executorlibs.Huya.Protocol.Models 7 | { 8 | public class PerSuffixInfo : ITarType // DecorationInfo 9 | { 10 | public int AppId; 11 | 12 | public int ViewType; 13 | 14 | public ArraySegment Data; 15 | 16 | public long SourceId; 17 | 18 | public int Type; 19 | 20 | public void ReadFrom(ref TarReader reader) 21 | { 22 | AppId = reader.Read(); 23 | ViewType = reader.Read(); 24 | Data = reader.Read(); 25 | SourceId = reader.Read(); 26 | Type = reader.Read(); 27 | } 28 | 29 | public void WriteTo(ref TarWriter writer) 30 | { 31 | throw new NotSupportedException(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Executorlibs.Huya.Protocol/Models/PushMessageV2.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.TarProtocol.IO; 2 | using Executorlibs.TarProtocol.Models; 3 | using Executorlibs.TarProtocol.Models.Primitives; 4 | 5 | namespace Executorlibs.Huya.Protocol.Models 6 | { 7 | public class PushMessageV2 : ITarType 8 | { 9 | public string GroupId = null!; 10 | 11 | public WsMsgItem[] Msgs = null!; 12 | 13 | public void ReadFrom(ref TarReader reader) 14 | { 15 | GroupId = reader.Read(); 16 | Msgs = reader.Read>(); 17 | } 18 | 19 | public void WriteTo(ref TarWriter writer) 20 | { 21 | new TarString(0, GroupId).WriteTo(ref writer); 22 | new TarList(1, Msgs).WriteTo(ref writer); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Executorlibs.Huya.Protocol/Models/TagInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Executorlibs.TarProtocol.IO; 3 | using Executorlibs.TarProtocol.Models; 4 | using Executorlibs.TarProtocol.Models.Primitives; 5 | 6 | namespace Executorlibs.Huya.Protocol.Models 7 | { 8 | public class TagInfo : ITarType 9 | { 10 | public int AppId; 11 | 12 | public string Name = null!; 13 | 14 | public void ReadFrom(ref TarReader reader) 15 | { 16 | AppId = reader.Read(); 17 | Name = reader.Read(); 18 | } 19 | 20 | public void WriteTo(ref TarWriter writer) 21 | { 22 | throw new NotSupportedException(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Executorlibs.Huya.Protocol/Models/UserInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Executorlibs.TarProtocol.IO; 3 | using Executorlibs.TarProtocol.Models; 4 | using Executorlibs.TarProtocol.Models.Primitives; 5 | 6 | namespace Executorlibs.Huya.Protocol.Models 7 | { 8 | /// 9 | /// 表示用户的基本信息。即用户名和用户Id 10 | /// 11 | /// 12 | /// 对应 UidNickName 13 | /// 14 | public class UserInfo : ITarType 15 | { 16 | public long UserId; 17 | 18 | public string UserName = null!; 19 | 20 | public void ReadFrom(ref TarReader reader) 21 | { 22 | UserId = reader.Read(); 23 | UserName = reader.Read(); 24 | } 25 | 26 | public void WriteTo(ref TarWriter writer) 27 | { 28 | throw new NotImplementedException(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Executorlibs.Huya.Protocol/Models/WsMsgItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Executorlibs.TarProtocol.IO; 3 | using Executorlibs.TarProtocol.Models; 4 | using Executorlibs.TarProtocol.Models.Primitives; 5 | 6 | namespace Executorlibs.Huya.Protocol.Models 7 | { 8 | public class WsMsgItem : ITarType 9 | { 10 | public long Uri; 11 | 12 | public ArraySegment Msg; 13 | 14 | public long MsgId; 15 | 16 | public void ReadFrom(ref TarReader reader) 17 | { 18 | Uri = reader.Read(); 19 | Msg = reader.Read(); 20 | MsgId = reader.Read(); 21 | } 22 | 23 | public void WriteTo(ref TarWriter writer) 24 | { 25 | new TarInt64(0, Uri).WriteTo(ref writer); 26 | new TarByteArray(1, Msg).WriteTo(ref writer); 27 | new TarInt64(2, MsgId).WriteTo(ref writer); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Executorlibs.Huya.Protocol/Options/HuyaClientOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Executorlibs.Huya.Protocol.Options 4 | { 5 | public class HuyaClientOptions 6 | { 7 | public long RoomId { get; set; } 8 | 9 | public TimeSpan HeartbeatInterval { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Executorlibs.Huya.Protocol/Parsers/Attributes/RegisterHuyaParserAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Executorlibs.MessageFramework.Parsers.Attributes; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Executorlibs.Huya.Protocol.Parsers.Attributes 6 | { 7 | 8 | /// 9 | /// 标记一个消息类、消息接口或者消息处理类所需要使用的 10 | /// 11 | public sealed class RegisterHuyaParserAttribute : RegisterParserAttribute 12 | { 13 | /// 14 | /// 使用给定的 初始化 的新实例 15 | /// 16 | /// 的类型 17 | public RegisterHuyaParserAttribute(Type implementationType) : this(implementationType, null) 18 | { 19 | 20 | } 21 | 22 | public RegisterHuyaParserAttribute(Type implementationType, ServiceLifetime? lifetime) : base(implementationType, lifetime) 23 | { 24 | 25 | } 26 | 27 | protected override Type GetServiceType(Type implementationType) 28 | { 29 | Type openGeneric = typeof(IHuyaMessageParser<>); 30 | foreach (Type interfaceType in implementationType.GetInterfaces()) 31 | { 32 | if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == openGeneric) 33 | { 34 | return typeof(IHuyaMessageParser); 35 | } 36 | } 37 | throw new ArgumentException($"给定的 {implementationType.Name} 不实现 {openGeneric.Name}", nameof(implementationType)); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Executorlibs.Huya.Protocol/Parsers/HuyaMessageParser.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Huya.Protocol.Models.General; 2 | using Executorlibs.MessageFramework.Parsers; 3 | 4 | namespace Executorlibs.Huya.Protocol.Parsers 5 | { 6 | /// 7 | /// 表示处理B站消息的 8 | /// 9 | public interface IHuyaMessageParser : IMessageParser 10 | { 11 | 12 | } 13 | 14 | /// 15 | /// 表示处理B站消息的 16 | /// 17 | /// 18 | public interface IHuyaMessageParser : IHuyaMessageParser, 19 | IMessageParser where TMessage : IHuyaMessage 20 | { 21 | 22 | } 23 | 24 | public abstract class HuyaMessageParser : MessageParser, IHuyaMessageParser where TMessage : IHuyaMessage 25 | { 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Executorlibs.Huya.Protocol/Services/IHuyaRequestDispatcher.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Executorlibs.Huya.Protocol.Clients; 4 | using Executorlibs.TarProtocol.Models; 5 | 6 | namespace Executorlibs.Huya.Protocol.Services 7 | { 8 | public interface IHuyaRequestDispatcher where TRequest : ITarType where TResponse : ITarType 9 | { 10 | Task InvokeAsync(IHuyaClient client, TRequest request, CancellationToken token = default); 11 | 12 | Task InvokeAsync(IHuyaClient client, TRequest request, string servant, string function, CancellationToken token = default); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Executorlibs.MessageFramework/Attributes/RegisterBaseAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Executorlibs.MessageFramework.Attributes 5 | { 6 | public abstract class RegisterBaseAttribute : Attribute 7 | { 8 | public Type ServiceType { get; } 9 | 10 | public Type ImplementationType { get; } 11 | 12 | public ServiceLifetime? Lifetime { get; } 13 | 14 | protected RegisterBaseAttribute(Type implementationType) : this(null, implementationType) 15 | { 16 | 17 | } 18 | 19 | protected RegisterBaseAttribute(Type implementationType, ServiceLifetime? lifetime) : this(null, implementationType, lifetime) 20 | { 21 | 22 | } 23 | 24 | protected RegisterBaseAttribute(Type? serviceType, Type implementationType) 25 | { 26 | ServiceType = serviceType ?? GetServiceType(implementationType); 27 | ImplementationType = implementationType; 28 | } 29 | 30 | protected RegisterBaseAttribute(Type? serviceType, Type implementationType, ServiceLifetime? lifetime) : this(serviceType, implementationType) 31 | { 32 | Lifetime = lifetime; 33 | } 34 | 35 | protected virtual Type GetServiceType(Type implementationType) 36 | { 37 | throw new NotSupportedException(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Executorlibs.MessageFramework/Clients/MessageClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Executorlibs.MessageFramework.Handlers; 4 | using Executorlibs.MessageFramework.Invoking; 5 | 6 | namespace Executorlibs.MessageFramework.Clients 7 | { 8 | public interface IMessageClient 9 | { 10 | PluginResistration AddPlugin(IMessageHandler handler); 11 | } 12 | 13 | public abstract class MessageClient : IMessageClient 14 | { 15 | protected abstract IEnumerable ResolveByHandler(Type handlerType); 16 | 17 | public PluginResistration AddPlugin(IMessageHandler handler) 18 | { 19 | LinkedList registrations = new LinkedList(); 20 | foreach (IMessageSubscription subscription in ResolveByHandler(handler.GetType())) 21 | { 22 | registrations.AddLast(subscription.AddHandler(handler)); 23 | } 24 | return new PluginResistration(registrations); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Executorlibs.MessageFramework/Clients/MessageDispatchClient.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Executorlibs.MessageFramework.Models.General; 3 | 4 | namespace Executorlibs.MessageFramework.Clients 5 | { 6 | public interface IMessageDispatchClient : IMessageClient where TMessage : IMessage 7 | { 8 | Task DispatchAsync(TRelatedMessage message) where TRelatedMessage : TMessage; 9 | } 10 | 11 | public abstract class MessageDispatchClient : MessageClient, IMessageDispatchClient where TMessage : IMessage 12 | { 13 | public abstract Task DispatchAsync(TRelatedMessage message) where TRelatedMessage : TMessage; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Executorlibs.MessageFramework/Executorlibs.MessageFramework.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | A complex message framework. 5 | message 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/Executorlibs.MessageFramework/Handlers/IContravarianceMessageHandler.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.MessageFramework.Clients; 2 | using Executorlibs.MessageFramework.Models.General; 3 | 4 | namespace Executorlibs.MessageFramework.Handlers 5 | { 6 | public interface IContravarianceMessageHandler : IMessageHandler where TClient : IMessageClient 7 | where TMessage : IMessage 8 | { 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Executorlibs.MessageFramework/Handlers/IInvarianceMessageHandler.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.MessageFramework.Clients; 2 | using Executorlibs.MessageFramework.Models.General; 3 | 4 | namespace Executorlibs.MessageFramework.Handlers 5 | { 6 | public interface IInvarianceMessageHandler : IMessageHandler where TClient : IMessageClient 7 | where TMessage : IMessage 8 | { 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Executorlibs.MessageFramework/Handlers/IMessageHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Executorlibs.MessageFramework.Clients; 4 | using Executorlibs.MessageFramework.Models.General; 5 | 6 | namespace Executorlibs.MessageFramework.Handlers 7 | { 8 | public interface IMessageHandler 9 | { 10 | #if !NETSTANDARD2_0 11 | Task HandleMessageAsync(IMessageClient client, IMessage message) 12 | { 13 | throw new NotSupportedException("请使用泛型接口中的 HandleMessageAsync 方法。"); 14 | } 15 | #else 16 | Task HandleMessageAsync(IMessageClient client, IMessage message); 17 | #endif 18 | } 19 | 20 | public interface IMessageHandler : IMessageHandler where TClient : IMessageClient 21 | where TMessage : IMessage 22 | { 23 | Task HandleMessageAsync(TClient client, TMessage message); 24 | } 25 | 26 | public abstract class MessageHandler : IMessageHandler where TClient : IMessageClient 27 | where TMessage : IMessage 28 | { 29 | public abstract Task HandleMessageAsync(TClient client, TMessage message); 30 | 31 | public virtual Task HandleMessageAsync(IMessageClient client, IMessage message) 32 | { 33 | throw new NotSupportedException("请使用泛型接口中的HandleMessageAsync方法。"); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Executorlibs.MessageFramework/Invoking/Attributes/RegisterMessageSubscriptionAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Executorlibs.MessageFramework.Attributes; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Executorlibs.MessageFramework.Invoking.Attributes 6 | { 7 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] 8 | public class RegisterMessageSubscriptionAttribute : RegisterBaseAttribute 9 | { 10 | public RegisterMessageSubscriptionAttribute(Type implementationType) : this(null, implementationType) 11 | { 12 | 13 | } 14 | 15 | public RegisterMessageSubscriptionAttribute(Type implementationType, ServiceLifetime? lifetime) : this(null, implementationType, lifetime) 16 | { 17 | 18 | } 19 | 20 | public RegisterMessageSubscriptionAttribute(Type? serviceType, Type implementationType) : this(serviceType, implementationType, null) 21 | { 22 | 23 | } 24 | 25 | public RegisterMessageSubscriptionAttribute(Type? serviceType, Type implementationType, ServiceLifetime? lifetime) : base(serviceType, implementationType, lifetime) 26 | { 27 | 28 | } 29 | 30 | protected override Type GetServiceType(Type implementationType) 31 | { 32 | return typeof(IMessageSubscription); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Executorlibs.MessageFramework/Invoking/Attributes/RegisterMessageSubscriptionResolverAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Executorlibs.MessageFramework.Attributes; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Executorlibs.MessageFramework.Invoking.Attributes 6 | { 7 | public class RegisterMessageSubscriptionResolverAttribute : RegisterBaseAttribute 8 | { 9 | public RegisterMessageSubscriptionResolverAttribute(Type implementationType) : this(implementationType, null) 10 | { 11 | 12 | } 13 | 14 | public RegisterMessageSubscriptionResolverAttribute(Type implementationType, ServiceLifetime? lifetime) : base(implementationType, lifetime) 15 | { 16 | 17 | } 18 | 19 | protected override Type GetServiceType(Type implementationType) 20 | { 21 | Type openGeneric = typeof(IMessageSubscriptionResolver<,>); 22 | foreach (Type interfaceType in implementationType.GetInterfaces()) 23 | { 24 | if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == openGeneric) 25 | { 26 | return interfaceType; 27 | } 28 | } 29 | throw new ArgumentException($"给定的 {implementationType.Name} 不实现 {openGeneric.Name}", nameof(implementationType)); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Executorlibs.MessageFramework/Invoking/DynamicHandlerRegistration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Executorlibs.MessageFramework.Invoking 4 | { 5 | // see: https://source.dot.net/#System.Private.CoreLib/CancellationTokenRegistration.cs,2d80bf84f593cc0c 6 | public struct DynamicHandlerRegistration : IEquatable, IDisposable 7 | { 8 | private readonly long _id; 9 | private readonly MessageSubscription.RegistrationNode _node; 10 | 11 | internal DynamicHandlerRegistration(long id, MessageSubscription.RegistrationNode node) 12 | { 13 | _id = id; 14 | _node = node; 15 | } 16 | 17 | public void Dispose() 18 | { 19 | if (_node is MessageSubscription.RegistrationNode node) 20 | { 21 | _node.Registrations.Unregister(_id, node); 22 | } 23 | } 24 | 25 | public static bool operator ==(DynamicHandlerRegistration left, DynamicHandlerRegistration right) => left.Equals(right); 26 | 27 | public static bool operator !=(DynamicHandlerRegistration left, DynamicHandlerRegistration right) => !left.Equals(right); 28 | 29 | public override bool Equals(object? obj) => obj is DynamicHandlerRegistration other && Equals(other); 30 | 31 | public bool Equals(DynamicHandlerRegistration other) => _node == other._node && _id == other._id; 32 | 33 | public override int GetHashCode() => _node != null ? _node.GetHashCode() ^ _id.GetHashCode() : _id.GetHashCode(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Executorlibs.MessageFramework/Invoking/IMessageSubscription.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Executorlibs.MessageFramework.Clients; 4 | using Executorlibs.MessageFramework.Handlers; 5 | using Executorlibs.MessageFramework.Models.General; 6 | #if !NETSTANDARD2_0 7 | using System.Threading.Tasks; 8 | #endif 9 | 10 | namespace Executorlibs.MessageFramework.Invoking 11 | { 12 | public interface IMessageSubscription : IMessageHandler, IDisposable, IEnumerable 13 | { 14 | DynamicHandlerRegistration AddHandler(IMessageHandler handler); 15 | } 16 | 17 | public interface IMessageSubscription : IMessageSubscription, 18 | IMessageHandler where TClient : IMessageClient // 只允许实现一种泛型接口 19 | where TMessage : IMessage // 想实现多种的请自己解决CS8705 20 | { 21 | DynamicHandlerRegistration AddHandler(IMessageHandler handler); 22 | 23 | #if !NETSTANDARD2_0 24 | Task IMessageHandler.HandleMessageAsync(IMessageClient client, IMessage message) 25 | => HandleMessageAsync((TClient)client, (TMessage)message); 26 | #endif 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Executorlibs.MessageFramework/Invoking/MessageSubscription.RegistrationNode.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.MessageFramework.Handlers; 2 | 3 | // see: https://source.dot.net/System.Private.CoreLib/CancellationTokenSource.cs.html#e46e9cfd59295b58 4 | namespace Executorlibs.MessageFramework.Invoking 5 | { 6 | public partial class MessageSubscription 7 | { 8 | protected internal sealed class RegistrationNode 9 | { 10 | public readonly Registrations Registrations; 11 | public RegistrationNode? Prev; 12 | public RegistrationNode? Next; 13 | 14 | public long Id; 15 | public IMessageHandler? Handler; 16 | 17 | public RegistrationNode(Registrations registrations) 18 | { 19 | Registrations = registrations; 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Executorlibs.MessageFramework/Invoking/PluginResistration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Executorlibs.MessageFramework.Invoking 5 | { 6 | public struct PluginResistration : IDisposable 7 | { 8 | internal LinkedList? _registrations; 9 | 10 | public PluginResistration(LinkedList registrations) 11 | { 12 | _registrations = registrations; 13 | } 14 | 15 | public void Dispose() 16 | { 17 | if (_registrations is LinkedList registrations) 18 | { 19 | foreach (var registration in registrations) 20 | { 21 | registration.Dispose(); 22 | } 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Executorlibs.MessageFramework/Models/General/Message.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.MessageFramework.Models.General 2 | { 3 | /// 4 | /// 消息的基接口 5 | /// 6 | public interface IMessage 7 | { 8 | /// 9 | /// 是否拦截消息传递 10 | /// 11 | bool BlockRemainingHandlers { get; set; } 12 | } 13 | 14 | /// 15 | /// 消息的基本信息接口 16 | /// 17 | /// 原始消息数据类型 18 | /// 19 | /// 继承自 20 | /// 21 | public interface IMessage : IMessage 22 | { 23 | /// 24 | /// 原始消息信息 25 | /// 26 | TRawdata Rawdata { get; } 27 | } 28 | 29 | /// 30 | /// 实现消息的基本信息的抽象类 31 | /// 32 | public abstract class Message : IMessage 33 | { 34 | /// 35 | public virtual bool BlockRemainingHandlers { get; set; } 36 | } 37 | 38 | /// 39 | /// 原始消息数据类型 40 | public abstract class Message : Message, IMessage // 建议传消息只使用接口(方便继承) 41 | { 42 | /// 43 | public virtual TRawdata Rawdata { get; set; } = default!; // Parser 应当设定它为 non-default 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Executorlibs.MessageFramework/Parsers/Attributes/SuppressAutoMappingAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Executorlibs.MessageFramework.Parsers.Attributes 4 | { 5 | [AttributeUsage(AttributeTargets.Class)] 6 | public sealed class SuppressAutoMappingAttribute : Attribute 7 | { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Executorlibs.MessageFramework/Parsers/IMappableMessageParser.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.MessageFramework.Models.General; 2 | 3 | namespace Executorlibs.MessageFramework.Parsers 4 | { 5 | /// 6 | /// 可用特定的 作为键的 7 | /// 8 | /// 9 | /// 本接口仅用于暴露 使用, 不约束 TRawdata 和 TMessage 10 | /// 11 | /// 要作为键的类型 12 | public interface IMappableMessageParser 13 | { 14 | /// 15 | /// 用于在外部作为键的属性 16 | /// 17 | TKey Key { get; } 18 | } 19 | 20 | /// 21 | /// 可用特定的 作为键的 22 | /// 23 | /// 要作为键的类型 24 | /// 原始消息数据类型 25 | /// 消息类型 26 | public interface IMappableMessageParser : IMappableMessageParser, 27 | IMessageParser where TMessage : IMessage 28 | { 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Executorlibs.MessageFramework/Parsers/IMessageParserResolver.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Executorlibs.MessageFramework.Parsers 4 | { 5 | public interface IMessageParserResolver where TParserService : IMessageParser 6 | { 7 | TParserService? ResolveParser(in TRawdata rawdata); 8 | 9 | IEnumerable ResolveParsers(in TRawdata rawdata); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Apis/NeteaseMusicApis.CheckMusicStatus.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Net.Http; 4 | using System.Text.Json; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using Executorlibs.NeteaseMusic.Models; 8 | using Executorlibs.Shared.Exceptions; 9 | 10 | namespace Executorlibs.NeteaseMusic.Apis 11 | { 12 | public static partial class NeteaseMusicApis 13 | { 14 | /// 15 | /// 检查给定ID对应的音乐有无版权 16 | /// 17 | /// 音乐ID 18 | /// 19 | public static async Task> CheckMusicStatusAsync(HttpClient client, long[] songIds, Quality quality, CancellationToken token = default) 20 | { 21 | using JsonDocument j = await GetPlayerUrlResponseAsync(client, songIds, Quality.SuperQuality, token).ConfigureAwait(false); 22 | JsonElement root = j.RootElement; 23 | if (root.GetProperty("code").GetInt32() == 200) 24 | { 25 | return root.GetProperty("data").EnumerateArray().ToDictionary(p => p.GetProperty("id").GetInt64(), p => p.GetProperty("code").GetInt32() == 200); 26 | } 27 | throw new UnknownResponseException(root); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Apis/NeteaseMusicApis.GetCsrfToken.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Net; 4 | using System.Net.Http; 5 | using Executorlibs.Shared.Exceptions; 6 | 7 | namespace Executorlibs.NeteaseMusic.Apis 8 | { 9 | public static partial class NeteaseMusicApis 10 | { 11 | private static string GetCsrfToken(HttpClientv2 client) 12 | { 13 | Cookie? cookie = client.Cookie.GetCookies(new Uri("http://music.163.com/")).OfType().FirstOrDefault(p => p.Name == "__csrf"); 14 | if (cookie == null) 15 | { 16 | throw new InvalidCookieException(); 17 | } 18 | return cookie.Value; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Apis/NeteaseMusicApis.GetPlayerUrlResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Net.Http; 3 | using System.Text.Json; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Executorlibs.NeteaseMusic.Crypto; 7 | using Executorlibs.NeteaseMusic.Models; 8 | using Executorlibs.Shared.Extensions; 9 | 10 | namespace Executorlibs.NeteaseMusic.Apis 11 | { 12 | public static partial class NeteaseMusicApis 13 | { 14 | /// 15 | /// 获取版权以及下载链接 16 | /// 17 | /// 18 | /// 19 | /// 20 | /// 21 | /// 22 | private static Task GetPlayerUrlResponseAsync(HttpClient client, long[] songIds, Quality bitRate = Quality.SuperQuality, CancellationToken token = default) 23 | { 24 | IDictionary data = new Dictionary 25 | { 26 | ["ids"] = songIds, 27 | ["br"] = (int)bitRate 28 | }; 29 | CryptoHelper.EApiEncryptedData encrypted = CryptoHelper.EApiEncrypt(data, "/api/song/enhance/player/url"); 30 | return client.PostAsync("https://interface3.music.163.com/eapi/song/enhance/player/url", encrypted.GetContent(), token).GetJsonAsync(token); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Apis/NeteaseMusicApis.GetUserInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Http; 2 | using System.Text.Json; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using Executorlibs.NeteaseMusic.Models; 6 | using Executorlibs.Shared.Exceptions; 7 | using Executorlibs.Shared.Extensions; 8 | 9 | namespace Executorlibs.NeteaseMusic.Apis 10 | { 11 | public static partial class NeteaseMusicApis 12 | { 13 | public static async Task GetUserInfoAsync(HttpClientv2 client, CancellationToken token = default) 14 | { 15 | using JsonDocument j = await client.GetAsync("https://music.163.com/api/nuser/account/get", token).GetJsonAsync(token).ConfigureAwait(false); 16 | JsonElement root = j.RootElement; 17 | if (root.GetProperty("code").GetInt32() == 0) 18 | { 19 | JsonElement profile = root.GetProperty("profile"); 20 | if (profile.ValueKind == JsonValueKind.Null) 21 | { 22 | throw new InvalidCookieException(); 23 | } 24 | return new UserInfo(profile.GetProperty("nickname").GetString()!, profile.GetProperty("userId").GetInt64(), profile.GetProperty("vipType").GetInt32()); 25 | } 26 | throw new UnknownResponseException(root); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Apis/NeteaseMusicApis.GetWebPlayerUrlResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Net.Http; 3 | using System.Text.Json; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Executorlibs.NeteaseMusic.Crypto; 7 | using Executorlibs.NeteaseMusic.Models; 8 | using Executorlibs.Shared.Extensions; 9 | 10 | namespace Executorlibs.NeteaseMusic.Apis 11 | { 12 | public static partial class NeteaseMusicApis 13 | { 14 | /// 15 | /// 获取版权以及下载链接 16 | /// 17 | /// 18 | /// 19 | /// 20 | /// 21 | /// 22 | private static Task GetWebPlayerUrlResponseAsync(HttpClient client, long[] songIds, Quality bitRate = Quality.SuperQuality, CancellationToken token = default) 23 | { 24 | IDictionary data = new Dictionary 25 | { 26 | ["ids"] = songIds, 27 | ["br"] = (int)bitRate 28 | }; 29 | CryptoHelper.WebApiEncryptedData encrypted = CryptoHelper.WebApiEncrypt(data); 30 | return client.PostAsync("https://music.163.com/weapi/song/enhance/player/url", encrypted.GetContent(), token).GetJsonAsync(token); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Apis/NeteaseMusicApis.Logout.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Net.Http; 3 | using System.Text.Json; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Executorlibs.NeteaseMusic.Crypto; 7 | using Executorlibs.Shared.Exceptions; 8 | using Executorlibs.Shared.Extensions; 9 | 10 | namespace Executorlibs.NeteaseMusic.Apis 11 | { 12 | public static partial class NeteaseMusicApis 13 | { 14 | public static async Task LogoutAsync(HttpClientv2 client, CancellationToken token = default) 15 | { 16 | IDictionary data = new Dictionary 17 | { 18 | ["csrf_token"] = GetCsrfToken(client), 19 | }; 20 | CryptoHelper.WebApiEncryptedData encrypted = CryptoHelper.WebApiEncrypt(data); 21 | using JsonDocument j = await client.PostAsync("https://music.163.com/weapi/logout", encrypted.GetContent(), token).GetJsonAsync(token).ConfigureAwait(false); 22 | JsonElement root = j.RootElement; 23 | if (root.GetProperty("code").GetInt32() != 0) 24 | { 25 | throw new UnknownResponseException(root); 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Apis/NeteaseMusicApis.Search.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Net.Http; 3 | using System.Text.Json; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Executorlibs.NeteaseMusic.Crypto; 7 | using Executorlibs.NeteaseMusic.Models; 8 | using Executorlibs.Shared.Extensions; 9 | 10 | namespace Executorlibs.NeteaseMusic.Apis 11 | { 12 | public static partial class NeteaseMusicApis 13 | { 14 | /// 15 | /// 按给定的信息执行搜索, 并返回响应体 16 | /// 17 | /// 关键词 18 | /// 搜索类型 19 | /// 返回的json中,实体个数上限 20 | /// 偏移量 21 | /// 服务器返回的Json 22 | public static Task SearchAsync(HttpClient client, string keyWords, SearchType type, int pageSize = 30, int offset = 0, CancellationToken token = default) 23 | { 24 | IDictionary data = new Dictionary 25 | { 26 | ["s"] = keyWords, 27 | ["type"] = (int)type, 28 | ["limit"] = pageSize, 29 | ["offset"] = offset 30 | }; 31 | CryptoHelper.WebApiEncryptedData encrypted = CryptoHelper.WebApiEncrypt(data); 32 | return client.PostAsync("https://music.163.com/weapi/cloudsearch/get/web", encrypted.GetContent(), token).GetJsonAsync(token); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Apis/NeteaseMusicApis.SearchPlaylistAsync.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Net.Http; 3 | using System.Text.Json; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Executorlibs.NeteaseMusic.Models; 7 | using Executorlibs.Shared.Exceptions; 8 | 9 | namespace Executorlibs.NeteaseMusic.Apis 10 | { 11 | public static partial class NeteaseMusicApis 12 | { 13 | public static async Task SearchPlaylistsAsync(HttpClient client, string keywords, int pageSize = 30, int offset = 0, CancellationToken token = default) 14 | { 15 | using JsonDocument j = await SearchAsync(client, keywords, SearchType.SongList, pageSize, offset, token).ConfigureAwait(false); 16 | JsonElement root = j.RootElement; 17 | if (root.GetProperty("code").GetInt32() == 200) 18 | { 19 | return root.GetProperty("result").GetProperty("playlists").EnumerateArray().Select(PlaylistInfo.Parse).ToArray(); 20 | } 21 | throw new UnknownResponseException(root); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Apis/NeteaseMusicApis.SearchSongs.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Net.Http; 4 | using System.Text.Json; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using Executorlibs.NeteaseMusic.Models; 8 | using Executorlibs.Shared.Exceptions; 9 | 10 | namespace Executorlibs.NeteaseMusic.Apis 11 | { 12 | public static partial class NeteaseMusicApis 13 | { 14 | /// 15 | /// 按给定的关键词搜索单曲 16 | /// 17 | /// 关键词 18 | /// 本次搜索返回的实例个数上限 19 | /// 偏移量 20 | public static async Task SearchSongsAsync(HttpClient client, string keywords, int pageSize = 30, int offset = 0, CancellationToken token = default) 21 | { 22 | using JsonDocument j = await SearchAsync(client, keywords, SearchType.Song, pageSize, offset, token).ConfigureAwait(false); 23 | JsonElement root = j.RootElement; 24 | if (root.GetProperty("code").GetInt32() == 200) 25 | { 26 | return root.GetProperty("result").GetProperty("songs").EnumerateArray().Select(SongInfo.Parse).ToArray(); 27 | } 28 | throw new UnknownResponseException(root); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Exceptions/LoginFailedException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Executorlibs.NeteaseMusic.Exceptions 4 | { 5 | public class LoginFailedException : Exception 6 | { 7 | public string Reason { get; set; } 8 | 9 | public LoginFailedException(string reason) : base($"登录失败。{reason}") 10 | { 11 | Reason = reason; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Exceptions/NoSuchPlaylistException.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.NeteaseMusic.Exceptions 2 | { 3 | public sealed class NoSuchPlaylistException : PlaylistException 4 | { 5 | public NoSuchPlaylistException() : this(0) 6 | { 7 | 8 | } 9 | 10 | public NoSuchPlaylistException(long playlistId) : base(playlistId, "给定的歌单不存在") 11 | { 12 | 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Exceptions/NoSuchSongException.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.NeteaseMusic.Exceptions 2 | { 3 | public sealed class NoSuchSongException : PlaylistException 4 | { 5 | public NoSuchSongException() : this(0) 6 | { 7 | 8 | } 9 | 10 | public NoSuchSongException(long playlistId) : base(playlistId, "给定的歌曲不存在") 11 | { 12 | 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Exceptions/PlaylistAccessDeniedException.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.NeteaseMusic.Exceptions 2 | { 3 | public sealed class PlaylistAccessDeniedException : PlaylistException 4 | { 5 | public PlaylistAccessDeniedException() : this(0) 6 | { 7 | 8 | } 9 | 10 | public PlaylistAccessDeniedException(long playlistId) : base(playlistId, "无权访问给定歌单") 11 | { 12 | 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Exceptions/PlaylistException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Executorlibs.NeteaseMusic.Exceptions 4 | { 5 | public abstract class PlaylistException : Exception 6 | { 7 | public long PlaylistId { get; set; } 8 | 9 | protected PlaylistException(long playlistId) : this(playlistId, null) 10 | { 11 | PlaylistId = playlistId; 12 | } 13 | 14 | protected PlaylistException(long playlistId, string? message) : base(message) 15 | { 16 | 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Executorlibs.NeteaseMusic.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Some Netease Music apis. 5 | netease 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Models/AlbumInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json; 3 | using Executorlibs.Shared; 4 | 5 | namespace Executorlibs.NeteaseMusic.Models 6 | { 7 | public class AlbumInfo 8 | { 9 | public long Id { get; } 10 | 11 | public string Name { get; } 12 | 13 | public DateTime PublishTime { get; } 14 | 15 | public int Count { get; } 16 | 17 | public AlbumInfo(long id, string name, DateTime publishTime, int count) 18 | { 19 | Id = id; 20 | Name = name; 21 | PublishTime = publishTime; 22 | Count = count; 23 | } 24 | 25 | public static AlbumInfo Parse(JsonElement node) 26 | { 27 | long publishTime = node.TryGetProperty("publishTime", out JsonElement publishTimeNode) ? publishTimeNode.GetInt64() : 0; 28 | int count = node.TryGetProperty("size", out JsonElement sizeNode) ? sizeNode.GetInt32() : 0; 29 | return new AlbumInfo(node.GetProperty("id").GetInt64(), node.GetProperty("name").GetString()!, Utils.UnixTime2DateTime(publishTime), count); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Models/ArtistInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | 3 | namespace Executorlibs.NeteaseMusic.Models 4 | { 5 | public class ArtistInfo 6 | { 7 | public long Id { get; } 8 | 9 | public string Name { get; } 10 | 11 | public ArtistInfo(long id, string name) 12 | { 13 | Id = id; 14 | Name = name; 15 | } 16 | 17 | public static ArtistInfo Parse(JsonElement node) 18 | { 19 | return new ArtistInfo(node.GetProperty("id").GetInt64(), node.GetProperty("name").GetString()!); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Models/DownloadSongInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json; 3 | 4 | namespace Executorlibs.NeteaseMusic.Models 5 | { 6 | public class DownloadSongInfo 7 | { 8 | public long Id { get; } 9 | 10 | public int Bitrate { get; } 11 | 12 | public Quality Quality { get; } 13 | 14 | public string Url { get; } 15 | 16 | public string Type { get; } 17 | 18 | public DateTime ExpireTime { get; } 19 | 20 | public DownloadSongInfo(long id, int bitrate, string url, string type) 21 | { 22 | Id = id; 23 | Bitrate = bitrate; 24 | Quality = bitrate switch // For self uploaded musics, bitrate may not be one of the Quality Enum values 25 | { 26 | <= (int)Quality.Unknown => Quality.Unknown, 27 | <= (int)Quality.LowQuality => Quality.LowQuality, 28 | <= (int)Quality.MediumQuality => Quality.MediumQuality, 29 | <= (int)Quality.HighQuality => Quality.HighQuality, 30 | _ => Quality.SuperQuality 31 | }; 32 | Url = url; 33 | Type = type; 34 | ExpireTime = DateTime.Now.AddMinutes(20); 35 | } 36 | 37 | 38 | public static DownloadSongInfo Parse(JsonElement node) 39 | { 40 | return new DownloadSongInfo(node.GetProperty("id").GetInt64(), node.GetProperty("br").GetInt32(), node.GetProperty("url").GetString()!, node.GetProperty("type").GetString()!); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Models/PlaylistInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | 3 | namespace Executorlibs.NeteaseMusic.Models 4 | { 5 | public class PlaylistInfo 6 | { 7 | public long Id { get; } 8 | 9 | public string? Name { get; } 10 | 11 | public PlaylistInfo(long id, string? name) 12 | { 13 | Id = id; 14 | Name = name; 15 | } 16 | 17 | public static PlaylistInfo Parse(JsonElement node) 18 | { 19 | return new PlaylistInfo(node.GetProperty("id").GetInt64(), null); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Models/Quality.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.NeteaseMusic.Models 2 | { 3 | public enum Quality 4 | { 5 | Unknown = 0, 6 | 7 | LowQuality = 128000, 8 | 9 | MediumQuality = 192000, 10 | 11 | HighQuality = 320000, 12 | 13 | SuperQuality = 999000 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Models/SearchType.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.NeteaseMusic.Models 2 | { 3 | public enum SearchType 4 | { 5 | /// 6 | /// 单曲 7 | /// 8 | Song = 1, 9 | /// 10 | /// 专辑 11 | /// 12 | Album = 10, 13 | /// 14 | /// 歌手 15 | /// 16 | Artist = 100, 17 | /// 18 | /// 歌单 19 | /// 20 | SongList = 1000, 21 | /// 22 | /// 用户 23 | /// 24 | User = 1002, 25 | /// 26 | /// MV 27 | /// 28 | Movie = 1004, 29 | /// 30 | /// 歌词 31 | /// 32 | Lyric = 1006, 33 | /// 34 | /// 电台 35 | /// 36 | Radio = 1009, 37 | /// 38 | /// 视频 39 | /// 40 | Video = 1014 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Models/UnikeyStatus.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.NeteaseMusic.Models 2 | { 3 | public enum UnikeyStatus 4 | { 5 | Expired = 800, 6 | 7 | Waiting = 801, 8 | 9 | Scanned = 802, 10 | 11 | Authorized = 803 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Executorlibs.NeteaseMusic/Models/UserInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.NeteaseMusic.Models 2 | { 3 | public class UserInfo 4 | { 5 | public string UserName { get; set; } 6 | 7 | public long UserId { get; set; } 8 | 9 | public int VipType { get; set; } 10 | 11 | public UserInfo(string userName, long userId, int vipType) 12 | { 13 | UserName = userName; 14 | UserId = userId; 15 | VipType = vipType; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared.Protocol/Clients/IProtocolClient.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Executorlibs.MessageFramework.Clients; 4 | 5 | namespace Executorlibs.Shared.Protocol.Clients 6 | { 7 | public interface IProtocolClient : IMessageClient 8 | { 9 | bool Connected { get; } 10 | 11 | Task ConnectAsync(CancellationToken token = default); 12 | 13 | void Disconnect(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared.Protocol/Executorlibs.Shared.Protocol.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Specialized for live platform message framework. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared.Protocol/Models/Danmaku/ICutOffMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.Shared.Protocol.Models.Danmaku 2 | { 3 | /// 4 | /// 全平台通用的当前直播间被直播管理员切断消息接口 5 | /// 6 | public interface ICutOffMessage : ILiveManagementMessage 7 | { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared.Protocol/Models/Danmaku/IDanmakuBaseMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.Shared.Protocol.Models.Danmaku 2 | { 3 | /// 4 | /// 全平台通用的弹幕基本信息接口 5 | /// 6 | public interface IDanmakuBaseMessage : IUserMessage 7 | { 8 | /// 9 | /// 弹幕内容 10 | /// 11 | string Comment { get; } 12 | } 13 | 14 | /// 15 | /// 全平台通用的弹幕基本信息接口 16 | /// 17 | /// 原始数据类型 18 | /// 用户Id的类型 19 | public interface IDanmakuBaseMessage : IDanmakuBaseMessage, IUserMessage 20 | { 21 | 22 | } 23 | 24 | public abstract class DanmakuBaseMessage : UserMessage, IDanmakuBaseMessage 25 | { 26 | public string Comment { get; set; } = null!; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared.Protocol/Models/Danmaku/IDanmakuMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.Shared.Protocol.Models.Danmaku 2 | { 3 | /// 4 | /// 全平台通用的弹幕信息接口 5 | /// 6 | public interface IDanmakuMessage : IDanmakuBaseMessage 7 | { 8 | /// 9 | /// 头衔信息 10 | /// 11 | ITitle? Title { get; } 12 | /// 13 | /// 勋章信息 14 | /// 15 | IMedal? Medal { get; } 16 | } 17 | 18 | /// 19 | /// 全平台通用的弹幕信息接口 20 | /// 21 | /// 原始数据类型 22 | /// 用户Id的类型 23 | public interface IDanmakuMessage : IDanmakuMessage, IDanmakuBaseMessage 24 | { 25 | /// 26 | /// 勋章信息 27 | /// 28 | new IMedal? Medal { get; } 29 | 30 | #if !NETSTANDARD2_0 31 | IMedal? IDanmakuMessage.Medal => Medal; 32 | #endif 33 | } 34 | 35 | public class DanmakuMessage : DanmakuBaseMessage, IDanmakuMessage 36 | { 37 | public IMedal? Medal { get; set; } 38 | 39 | public ITitle? Title { get; set; } 40 | 41 | #if NETSTANDARD2_0 42 | IMedal? IDanmakuMessage.Medal => Medal; 43 | #endif 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared.Protocol/Models/Danmaku/IEnterMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.Shared.Protocol.Models.Danmaku 2 | { 3 | /// 4 | /// 全平台通用的用户进入直播间消息接口 5 | /// 6 | public interface IEnterMessage : IUserMessage 7 | { 8 | 9 | } 10 | 11 | /// 12 | /// 全平台通用的用户进入直播间消息接口 13 | /// 14 | public interface IEnterMessage : IEnterMessage, IUserMessage 15 | { 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared.Protocol/Models/Danmaku/IFollowMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.Shared.Protocol.Models.Danmaku 2 | { 3 | /// 4 | /// 全平台通用的用户关注直播间消息接口 5 | /// 6 | public interface IFollowMessage : IUserMessage 7 | { 8 | 9 | } 10 | 11 | /// 12 | /// 全平台通用的用户关注直播间消息接口 13 | /// 14 | public interface IFollowMessage : IFollowMessage, IUserMessage 15 | { 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared.Protocol/Models/Danmaku/ILiveEndMessage.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Shared.Protocol.Models.General; 2 | 3 | namespace Executorlibs.Shared.Protocol.Models.Danmaku 4 | { 5 | /// 6 | /// 全平台通用的直播结束消息接口 7 | /// 8 | public interface ILiveEndMessage : IProtocolMessage 9 | { 10 | 11 | } 12 | 13 | /// 14 | /// 全平台通用的直播结束消息接口 15 | /// 16 | public interface ILiveEndMessage : ILiveEndMessage, IProtocolMessage 17 | { 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared.Protocol/Models/Danmaku/ILiveManagementMessage.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Shared.Protocol.Models.General; 2 | 3 | namespace Executorlibs.Shared.Protocol.Models.Danmaku 4 | { 5 | /// 6 | /// 全平台通用的超级管理员进行房间管理操作消息接口 7 | /// 8 | public interface ILiveManagementMessage : IProtocolMessage 9 | { 10 | /// 11 | /// 操作理由 12 | /// 13 | string? Message { get; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared.Protocol/Models/Danmaku/ILiveStartMessage.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Shared.Protocol.Models.General; 2 | 3 | namespace Executorlibs.Shared.Protocol.Models.Danmaku 4 | { 5 | /// 6 | /// 全平台通用的直播开始消息接口 7 | /// 8 | public interface ILiveStartMessage : IProtocolMessage 9 | { 10 | 11 | } 12 | 13 | /// 14 | /// 全平台通用的直播开始消息接口 15 | /// 16 | public interface ILiveStartMessage : ILiveStartMessage, IProtocolMessage 17 | { 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared.Protocol/Models/Danmaku/IRoomLockMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.Shared.Protocol.Models.Danmaku 2 | { 3 | /// 4 | /// 全平台通用的当前直播间被直播管理员关闭消息接口 5 | /// 6 | public interface IRoomLockMessage : ILiveManagementMessage 7 | { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared.Protocol/Models/Danmaku/ISendGiftBaseMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.Shared.Protocol.Models.Danmaku 2 | { 3 | /// 4 | /// 全平台通用的礼物基本信息接口 5 | /// 6 | public interface ISendGiftBaseMessage : IUserMessage 7 | { 8 | /// 9 | /// 礼物Id 10 | /// 11 | int GiftId { get; } // 存疑, 不知道其它平台的Id是不是一定为Int32 12 | /// 13 | /// 礼物名称 14 | /// 15 | string GiftName { get; } 16 | /// 17 | /// 礼物数量 18 | /// 19 | int GiftCount { get; } 20 | /// 21 | /// 礼物价格 (单位:元) 22 | /// 23 | double GiftPrice { get; } 24 | /// 25 | /// 是否为免费礼物 26 | /// 27 | bool IsFree { get; } 28 | } 29 | 30 | /// 31 | /// 全平台通用的礼物基本信息接口 32 | /// 33 | public interface ISendGiftBaseMessage : ISendGiftBaseMessage, IUserMessage 34 | { 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared.Protocol/Models/Danmaku/ITitle.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.Shared.Protocol.Models.Danmaku 2 | { 3 | /// 4 | /// 全平台通用的头衔基本信息接口 5 | /// 6 | public interface ITitle 7 | { 8 | /// 9 | /// 显示名称 10 | /// 11 | string Name { get; } 12 | /// 13 | /// 序号 14 | /// 15 | int Id { get; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared.Protocol/Models/Danmaku/IUserMessage.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Shared.Protocol.Models.General; 2 | 3 | namespace Executorlibs.Shared.Protocol.Models.Danmaku 4 | { 5 | /// 6 | /// 全平台通用的用户基本信息接口 7 | /// 8 | public interface IUserMessage : IProtocolMessage 9 | { 10 | /// 11 | /// 用户名 12 | /// 13 | string UserName { get; } 14 | 15 | object UserId { get; } 16 | } 17 | 18 | /// 19 | /// 全平台通用的用户基本信息接口 20 | /// 21 | /// 原始数据类型 22 | /// 用户Id的类型 23 | public interface IUserMessage : IUserMessage, IProtocolMessage 24 | { 25 | /// 26 | /// 用户Id 27 | /// 28 | new TUserId UserId { get; } 29 | 30 | #if !NETSTANDARD2_0 31 | object IUserMessage.UserId => UserId!; 32 | #endif 33 | } 34 | 35 | public abstract class UserMessage : ProtocolMessage, IUserMessage 36 | { 37 | public string UserName { get; set; } = null!; 38 | 39 | public TUserId UserId { get; set; } = default!; 40 | 41 | #if NETSTANDARD2_0 42 | object IUserMessage.UserId => UserId!; 43 | #endif 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared.Protocol/Models/Danmaku/IUserMutedMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.Shared.Protocol.Models.Danmaku 2 | { 3 | /// 4 | /// 全平台通用的用户被禁言消息接口 5 | /// 6 | public interface IUserMutedMessage : IUserMessage 7 | { 8 | 9 | } 10 | 11 | /// 12 | /// 全平台通用的用户被禁言消息接口 13 | /// 14 | public interface IUserMutedMessage : IUserMutedMessage, IUserMessage 15 | { 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared.Protocol/Models/Danmaku/IWarningMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.Shared.Protocol.Models.Danmaku 2 | { 3 | /// 4 | /// 全平台通用的当前直播间被直播管理员警告消息接口 5 | /// 6 | public interface IWarningMessage : ILiveManagementMessage 7 | { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared.Protocol/Models/Danmaku/PopularityMessage.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.Shared.Protocol.Models.General; 2 | 3 | namespace Executorlibs.Shared.Protocol.Models.Danmaku 4 | { 5 | /// 6 | /// 全平台通用的当前房间人气信息 7 | /// 8 | public interface IPopularityMessage : IProtocolMessage 9 | { 10 | /// 11 | /// 人气值 12 | /// 13 | ulong Popularity { get; } 14 | } 15 | 16 | /// 17 | /// 全平台通用的当前房间人气信息 18 | /// 19 | public interface IPopularityMessage : IProtocolMessage 20 | { 21 | 22 | } 23 | 24 | 25 | public class PopularityMessage : ProtocolMessage, IPopularityMessage 26 | { 27 | public ulong Popularity { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared.Protocol/Models/General/ConnectedMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.Shared.Protocol.Models.General 2 | { 3 | public enum ConnectReason 4 | { 5 | UserInitiated, 6 | 7 | PluginTriggered, 8 | 9 | ErrorEncountered, 10 | 11 | Others 12 | } 13 | 14 | public interface IConnectedMessage : IConnectionChangedMessage 15 | { 16 | ConnectReason Reason { get; } 17 | } 18 | 19 | public class ConnectedMessage : ConnectionChangedMessage, IConnectedMessage 20 | { 21 | public ConnectReason Reason { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared.Protocol/Models/General/ConnectionChangedMessage.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.MessageFramework.Models.General; 2 | 3 | namespace Executorlibs.Shared.Protocol.Models.General 4 | { 5 | public interface IConnectionChangedMessage : IMessage 6 | { 7 | 8 | } 9 | 10 | public class ConnectionChangedMessage : Message, IConnectionChangedMessage 11 | { 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared.Protocol/Models/General/DisconnectedMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | 4 | namespace Executorlibs.Shared.Protocol.Models.General 5 | { 6 | public interface IDisconnectedMessage : IConnectionChangedMessage 7 | { 8 | Exception? Exception { get; } 9 | 10 | CancellationToken Token { get; } 11 | } 12 | 13 | public class DisconnectedMessage : ConnectionChangedMessage, IDisconnectedMessage 14 | { 15 | public Exception? Exception { get; set; } 16 | 17 | public CancellationToken Token { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared/Exceptions/DuplicateOperationException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Executorlibs.Shared.Exceptions 4 | { 5 | public sealed class DuplicateOperationException : Exception 6 | { 7 | public DuplicateOperationException() : base("之前已经进行过此操作。") { } 8 | 9 | public DuplicateOperationException(string message) : base(message) { } 10 | 11 | public DuplicateOperationException(string message, Exception innerException) : base(message, innerException) { } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared/Exceptions/InvalidCookieException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Executorlibs.Shared.Exceptions 4 | { 5 | public sealed class InvalidCookieException : Exception 6 | { 7 | public InvalidCookieException() : base("给定的Cookie无效.") { } 8 | 9 | public InvalidCookieException(string message) : base(message) { } 10 | 11 | public InvalidCookieException(string message, Exception innerException) : base(message, innerException) { } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared/Exceptions/PermissionDeniedException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Executorlibs.Shared.Exceptions 4 | { 5 | public sealed class PermissionDeniedException : Exception 6 | { 7 | public PermissionDeniedException() : base("无权操作。") { } 8 | 9 | public PermissionDeniedException(string message) : base(message) { } 10 | 11 | public PermissionDeniedException(string message, Exception innerException) : base(message, innerException) { } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared/Executorlibs.Shared.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Misc classes, extensions, helpers. 4 | utils 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared/Extensions/HttpClientExtensions.PostByteArrayContent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net.Http; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | 6 | #pragma warning disable CS1573 // Parameter has no matching param tag in the XML comment (but other parameters do) 7 | namespace Executorlibs.Shared.Extensions 8 | { 9 | public static partial class HttpClientExtensions 10 | { 11 | /// The . 12 | /// The url the request is sent to. 13 | /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. 14 | /// 15 | public static Task PostAsync(this HttpClient client, Uri uri, byte[] content, CancellationToken token = default) 16 | => client.PostAsync(uri, new ByteArrayContent(content), token); 17 | 18 | /// The url the request is sent to. 19 | /// 20 | public static Task PostAsync(this HttpClient client, string url, byte[] content, CancellationToken token = default) 21 | => client.PostAsync(new Uri(url), content, token); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared/Extensions/HttpClientExtensions.PostEmptyContent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net.Http; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | 6 | namespace Executorlibs.Shared.Extensions 7 | { 8 | public static partial class HttpClientExtensions 9 | { 10 | /// 11 | public static Task PostAsync(this HttpClient client, Uri uri, CancellationToken token = default) 12 | => client.PostAsync(uri, null!, token); 13 | 14 | /// 15 | public static Task PostAsync(this HttpClient client, string url, CancellationToken token = default) 16 | => client.PostAsync(new Uri(url), token); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared/Extensions/HttpClientExtensions.Stream.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Net.Http; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | 6 | namespace Executorlibs.Shared.Extensions 7 | { 8 | public static partial class HttpClientExtensions 9 | { 10 | public static async Task GetStreamAsync(this Task responseTask, CancellationToken token = default) 11 | { 12 | HttpResponseMessage response = await responseTask.ConfigureAwait(false); 13 | HttpContent? c = response.Content; 14 | #if NET5_0_OR_GREATER 15 | return c != null ? await c.ReadAsStreamAsync(token) : Stream.Null; 16 | #else 17 | return c != null ? await c.ReadAsStreamAsync() : Stream.Null; 18 | #endif 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared/Extensions/HttpRequestHeadersExtension.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Http.Headers; 2 | 3 | namespace Executorlibs.Shared.Extensions 4 | { 5 | public static class HttpRequestHeadersExtension 6 | { 7 | public static void SetUserAgent(this HttpRequestHeaders headers, string userAgent) 8 | { 9 | HttpHeaderValueCollection ua = headers.UserAgent; 10 | ua.Clear(); 11 | ua.ParseAdd(userAgent); 12 | } 13 | 14 | public static void SetAccept(this HttpRequestHeaders headers, string accept) 15 | { 16 | HttpHeaderValueCollection a = headers.Accept; 17 | a.Clear(); 18 | a.ParseAdd(accept); 19 | } 20 | 21 | public static void SetAcceptLanguage(this HttpRequestHeaders headers, string acceptLanguage) 22 | { 23 | HttpHeaderValueCollection al = headers.AcceptLanguage; 24 | al.Clear(); 25 | al.ParseAdd(acceptLanguage); 26 | } 27 | 28 | public static void SetSecPolicy(this HttpRequestHeaders headers, string? mode = "cors", string? site = "same-site", string? dest = "empty") 29 | { 30 | if (!string.IsNullOrEmpty(mode)) 31 | { 32 | headers.Add("Sec-Fetch-Mode", mode); 33 | } 34 | if (!string.IsNullOrEmpty(site)) 35 | { 36 | headers.Add("Sec-Fetch-Site", site); 37 | } 38 | if (!string.IsNullOrEmpty(dest)) 39 | { 40 | headers.Add("Sec-Fetch-Dest", dest); 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared/Extensions/JsonElementExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Text.Json; 3 | 4 | namespace Executorlibs.Shared.Extensions 5 | { 6 | public static class JsonElementExtensions 7 | { 8 | public static bool HasValues(this JsonElement j) 9 | => j.ValueKind == JsonValueKind.Array ? j.EnumerateArray().Any() : j.ValueKind == JsonValueKind.Object && j.EnumerateObject().Any(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared/Extensions/StreamExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | 6 | namespace Executorlibs.Shared.Extensions 7 | { 8 | public static class StreamExtensions 9 | { 10 | public static ValueTask ReadFullyAsync(this Stream stream, byte[] buffer, CancellationToken token = default) 11 | => stream.ReadFullyAsync(buffer, 0, buffer.Length, token); 12 | 13 | public static async ValueTask ReadFullyAsync(this Stream stream, byte[] buffer, int offset, int size, CancellationToken token = default) 14 | { 15 | if (offset + size > buffer.Length) 16 | { 17 | throw new ArgumentException("Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection."); 18 | } 19 | while (size > 0) 20 | { 21 | #if !NETSTANDARD2_0 22 | int n = await stream.ReadAsync(new Memory(buffer, offset, size), token); 23 | #else 24 | int n = await stream.ReadAsync(buffer, offset, size, token); 25 | #endif 26 | if (n < 1) 27 | { 28 | throw new EndOfStreamException(); 29 | } 30 | offset += n; 31 | size -= n; 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared/Helpers/StringHelper.cs: -------------------------------------------------------------------------------- 1 | #if !NETSTANDARD2_0 2 | namespace Executorlibs.Shared.Helpers 3 | { 4 | public static unsafe class StringHelper 5 | { 6 | public static string FastAllocateString(int size) 7 | => string.Create(size, 0, static (_, _) => { }); 8 | } 9 | } 10 | #endif 11 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared/JsonConverters/ChangeTypeJsonConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json; 3 | using System.Text.Json.Serialization; 4 | 5 | namespace Executorlibs.Shared.JsonConverters 6 | { 7 | public class ChangeTypeJsonConverter : JsonConverter where TFrom : TTo 8 | { 9 | public override TTo Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 10 | { 11 | return JsonSerializer.Deserialize(ref reader, options)!; 12 | } 13 | 14 | public override void Write(Utf8JsonWriter writer, TTo value, JsonSerializerOptions options) 15 | { 16 | JsonSerializer.Serialize(writer, (TFrom?)value, options); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared/JsonConverters/DateTimeJsonConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json; 3 | using System.Text.Json.Serialization; 4 | 5 | namespace Executorlibs.Shared.JsonConverters 6 | { 7 | public class DateTimeJsonConverter : JsonConverter 8 | { 9 | public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 10 | { 11 | return DateTime.Parse(reader.GetString()!); 12 | } 13 | 14 | public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) 15 | { 16 | writer.WriteStringValue(value.ToString("yyyy-MM-dd HH:mm:ss")); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared/JsonConverters/Double2StringJsonConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json; 3 | using System.Text.Json.Serialization; 4 | 5 | namespace Executorlibs.Shared.JsonConverters 6 | { 7 | public class Double2StringJsonConverter : JsonConverter 8 | { 9 | private readonly int _precision; 10 | 11 | public Double2StringJsonConverter() 12 | { 13 | _precision = -1; 14 | } 15 | 16 | public Double2StringJsonConverter(int precision) 17 | { 18 | _precision = precision; 19 | } 20 | 21 | public override double Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 22 | { 23 | return double.Parse(reader.GetString()!); 24 | } 25 | 26 | public override void Write(Utf8JsonWriter writer, double value, JsonSerializerOptions options) 27 | { 28 | writer.WriteStringValue(value.ToString(_precision switch 29 | { 30 | -1 => null, 31 | 0 => "0", 32 | _ => "0." + new string('0', _precision), 33 | })); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared/JsonConverters/DoubleJsonConverterAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace Executorlibs.Shared.JsonConverters 5 | { 6 | public class DoubleJsonConverterAttribute : JsonConverterAttribute 7 | { 8 | private readonly int _precision; 9 | 10 | public DoubleJsonConverterAttribute(int precision) : base(null!) 11 | { 12 | _precision = precision; 13 | } 14 | 15 | public override JsonConverter? CreateConverter(Type typeToConvert) 16 | { 17 | return new Double2StringJsonConverter(_precision); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared/JsonConverters/NullableJsonConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json; 3 | using System.Text.Json.Serialization; 4 | 5 | namespace Executorlibs.Shared.JsonConverters 6 | { 7 | public class NullableJsonConverter : JsonConverter where T : struct 8 | where TConverter : JsonConverter, new() 9 | { 10 | public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 11 | { 12 | TConverter converter = new TConverter(); 13 | return converter.Read(ref reader, typeof(T), options); 14 | } 15 | 16 | public override void Write(Utf8JsonWriter writer, T? value, JsonSerializerOptions options) 17 | { 18 | TConverter converter = new TConverter(); 19 | converter.Write(writer, value.GetValueOrDefault(), options); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared/JsonConverters/TimeSpanJsonConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json; 3 | using System.Text.Json.Serialization; 4 | 5 | namespace Executorlibs.Shared.JsonConverters 6 | { 7 | public class TimeSpanJsonConverter : JsonConverter 8 | { 9 | public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 10 | { 11 | return TimeSpan.Parse(reader.GetString()!); 12 | } 13 | 14 | public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options) 15 | { 16 | writer.WriteStringValue(value.ToString()); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared/JsonConverters/UnixTimeStampJsonConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json; 3 | using System.Text.Json.Serialization; 4 | 5 | namespace Executorlibs.Shared.JsonConverters 6 | { 7 | public class UnixTimeStampJsonConverter : JsonConverter 8 | { 9 | public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 10 | { 11 | return reader.TokenType switch 12 | { 13 | JsonTokenType.Number => Utils.UnixTime2DateTime(reader.GetInt32()), 14 | JsonTokenType.String => DateTime.Parse(reader.GetString()!), 15 | _ => throw new ArgumentException($"Expected unix timestamp or datetime string, got {reader.TokenType}") 16 | }; 17 | } 18 | 19 | public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) 20 | { 21 | writer.WriteNumberValue(Utils.DateTime2UnixTimeSeconds(value)); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared/Net/Http/PCHttpClient.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Http; 2 | 3 | namespace Executorlibs.Shared.Net.Http 4 | { 5 | public class PCHttpClient : HttpClientv2 6 | { 7 | public PCHttpClient() 8 | { 9 | DefaultRequestHeaders.Accept.ParseAdd("*/*"); 10 | DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66"); 11 | } 12 | 13 | public PCHttpClient(HttpMessageHandler handler) : base(handler) 14 | { 15 | DefaultRequestHeaders.Accept.ParseAdd("*/*"); 16 | DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66"); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Executorlibs.Shared/System/Net/Http/HttpClientv2.cs: -------------------------------------------------------------------------------- 1 | namespace System.Net.Http 2 | { 3 | public abstract class HttpClientv2 : HttpClient 4 | { 5 | protected readonly HttpMessageHandler _handler; 6 | 7 | public CookieContainer Cookie 8 | { 9 | get => _handler switch 10 | { 11 | HttpClientHandler clientHandler => clientHandler.CookieContainer, 12 | #if NETCOREAPP2_1_OR_GREATER 13 | SocketsHttpHandler socketsHandler => socketsHandler.CookieContainer, 14 | #endif 15 | _ => throw new NotSupportedException() 16 | }; 17 | set => _ = _handler switch 18 | { 19 | HttpClientHandler clientHandler => clientHandler.CookieContainer = value, 20 | #if NETCOREAPP2_1_OR_GREATER 21 | SocketsHttpHandler socketsHandler => socketsHandler.CookieContainer = value, 22 | #endif 23 | _ => throw new NotSupportedException() 24 | }; 25 | } 26 | 27 | public HttpClientv2() : this(new HttpClientHandler()) 28 | { 29 | 30 | } 31 | 32 | public HttpClientv2(HttpMessageHandler handler) : base(handler) 33 | { 34 | _handler = handler; 35 | } 36 | 37 | public void ClearCookie() 38 | { 39 | Cookie = new CookieContainer(); 40 | } 41 | 42 | public void SetCookie(Uri uri, string cookie) 43 | { 44 | Cookie.SetCookies(uri, cookie); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Executorlibs.TarProtocol/Exceptions/MalformedTarMessageException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Executorlibs.TarProtocol.Exceptions 4 | { 5 | public class MalformedTarMessageException : Exception 6 | { 7 | private const string DefaultMessage = "给定的Tar消息不完整。"; 8 | 9 | public MalformedTarMessageException() : this(DefaultMessage) 10 | { 11 | 12 | } 13 | 14 | public MalformedTarMessageException(string? message) : this(message, null) 15 | { 16 | 17 | } 18 | 19 | public MalformedTarMessageException(string? message, Exception? innerException) : base(message ?? DefaultMessage, innerException) 20 | { 21 | 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Executorlibs.TarProtocol/Exceptions/TarTypeMismatchException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Executorlibs.TarProtocol.Models; 3 | 4 | namespace Executorlibs.TarProtocol.Exceptions 5 | { 6 | public class TarTypeMismatchException : Exception 7 | { 8 | private const string DefaultMessage = "给定的Tar消息类型与期望的类型不符。"; 9 | 10 | public TarType? Expected { get; } 11 | 12 | public TarType? Given { get; } 13 | 14 | public TarTypeMismatchException() : this(DefaultMessage) 15 | { 16 | 17 | } 18 | 19 | public TarTypeMismatchException(string? message) : this(message, null) 20 | { 21 | 22 | } 23 | 24 | public TarTypeMismatchException(string? message, Exception? innerException) : base(message ?? DefaultMessage, innerException) 25 | { 26 | 27 | } 28 | 29 | public TarTypeMismatchException(TarType expected, TarType given) : this(expected, given, null) 30 | { 31 | 32 | } 33 | 34 | public TarTypeMismatchException(TarType expected, TarType given, string? message) : this(expected, given, message, null) 35 | { 36 | 37 | } 38 | 39 | public TarTypeMismatchException(TarType expected, TarType given, string? message, Exception? innerException) : this(message, innerException) 40 | { 41 | Expected = expected; 42 | Given = given; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Executorlibs.TarProtocol/Executorlibs.TarProtocol.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0;net5.0 5 | Tencent total application framework protocol implementation. 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/Executorlibs.TarProtocol/Models/IReadableTarType.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.TarProtocol.IO; 2 | 3 | namespace Executorlibs.TarProtocol.Models 4 | { 5 | public interface IReadableTarType 6 | { 7 | void ReadFrom(ref TarReader reader); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Executorlibs.TarProtocol/Models/ITarType.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.TarProtocol.Models 2 | { 3 | public interface ITarType : IReadableTarType, IWritableTarType 4 | { 5 | 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/Executorlibs.TarProtocol/Models/IWritableTarType.cs: -------------------------------------------------------------------------------- 1 | using Executorlibs.TarProtocol.IO; 2 | 3 | namespace Executorlibs.TarProtocol.Models 4 | { 5 | public interface IWritableTarType 6 | { 7 | void WriteTo(ref TarWriter writer); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Executorlibs.TarProtocol/Models/Primitives/TarStructBegin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using Executorlibs.TarProtocol.IO; 4 | 5 | namespace Executorlibs.TarProtocol.Models.Primitives 6 | { 7 | [DebuggerDisplay("[{Header.Tag}] %StructBegin%")] 8 | public struct TarStructBegin : ITarType 9 | { 10 | public TarHeader Header; 11 | 12 | public TarStructBegin(byte tag) 13 | { 14 | Header = new TarHeader(TarType.StructBegin, tag); 15 | } 16 | 17 | public void ReadFrom(ref TarReader reader) 18 | { 19 | Header = reader.ReadHeader(); 20 | if (Header.Type != TarType.StructBegin) 21 | { 22 | throw new InvalidOperationException(); 23 | } 24 | } 25 | 26 | public void WriteTo(ref TarWriter writer) 27 | { 28 | writer.WriteHeader(Header); 29 | } 30 | 31 | public override bool Equals(object? obj) 32 | { 33 | return obj is TarStructBegin value && Equals(value); 34 | } 35 | 36 | public bool Equals(TarStructBegin value) 37 | { 38 | return value.Header == Header; 39 | } 40 | 41 | public override int GetHashCode() 42 | { 43 | return Header.GetHashCode(); 44 | } 45 | 46 | public static bool operator ==(TarStructBegin left, TarStructBegin right) 47 | { 48 | return left.Equals(right); 49 | } 50 | 51 | public static bool operator !=(TarStructBegin left, TarStructBegin right) 52 | { 53 | return !(left == right); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Executorlibs.TarProtocol/Models/Primitives/TarStructEnd.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using Executorlibs.TarProtocol.IO; 4 | 5 | #pragma warning disable IDE0060 // Remove unused parameter 6 | namespace Executorlibs.TarProtocol.Models.Primitives 7 | { 8 | [DebuggerDisplay("[0] %StructEnd%")] 9 | public struct TarStructEnd : ITarType 10 | { 11 | public static TarStructEnd Instance => new TarStructEnd 12 | { 13 | Header = new TarHeader(TarType.StructEnd, 0) 14 | }; 15 | 16 | public TarHeader Header; 17 | 18 | public void ReadFrom(ref TarReader Reader) 19 | { 20 | Header = Reader.ReadHeader(); 21 | if (Header.Type != TarType.StructEnd) 22 | { 23 | throw new InvalidOperationException(); 24 | } 25 | } 26 | 27 | public void WriteTo(ref TarWriter writer) 28 | { 29 | writer.WriteHeader(Header); 30 | } 31 | 32 | public override bool Equals(object? obj) 33 | { 34 | return obj is TarStructEnd value && Equals(value); 35 | } 36 | 37 | public bool Equals(TarStructEnd value) 38 | { 39 | return value.Header == Header; 40 | } 41 | 42 | public override int GetHashCode() 43 | { 44 | return Header.GetHashCode(); 45 | } 46 | 47 | public static bool operator ==(TarStructEnd _, TarStructEnd __) 48 | { 49 | return true; 50 | } 51 | 52 | public static bool operator !=(TarStructEnd _, TarStructEnd __) 53 | { 54 | return false; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Executorlibs.TarProtocol/Models/Primitives/TarZero.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using Executorlibs.TarProtocol.IO; 4 | 5 | namespace Executorlibs.TarProtocol.Models.Primitives 6 | { 7 | [DebuggerDisplay("[{Header.Tag}] 0")] 8 | public struct TarZero : ITarType 9 | { 10 | public TarHeader Header; 11 | 12 | public TarZero(byte tag) 13 | { 14 | Header = new TarHeader(TarType.Zero, tag); 15 | } 16 | 17 | public void ReadFrom(ref TarReader reader) 18 | { 19 | Header = reader.ReadHeader(); 20 | if (Header.Type != TarType.Zero) 21 | { 22 | throw new InvalidOperationException(); 23 | } 24 | } 25 | 26 | public void WriteTo(ref TarWriter writer) 27 | { 28 | writer.WriteHeader(Header); 29 | } 30 | 31 | public override bool Equals(object? obj) 32 | { 33 | return obj is TarZero value && Equals(value); 34 | } 35 | 36 | public bool Equals(TarZero value) 37 | { 38 | return value.Header == Header; 39 | } 40 | 41 | public override int GetHashCode() 42 | { 43 | return Header.GetHashCode(); 44 | } 45 | 46 | public static implicit operator byte(TarZero _) 47 | { 48 | return 0; 49 | } 50 | 51 | public static bool operator ==(TarZero left, TarZero right) 52 | { 53 | return left.Equals(right); 54 | } 55 | 56 | public static bool operator !=(TarZero left, TarZero right) 57 | { 58 | return !(left == right); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Executorlibs.TarProtocol/Models/TarType.cs: -------------------------------------------------------------------------------- 1 | namespace Executorlibs.TarProtocol.Models 2 | { 3 | public enum TarType : byte 4 | { 5 | Byte = 0, 6 | Short = 1, 7 | Int = 2, 8 | Long = 3, 9 | Float = 4, 10 | Double = 5, 11 | String1 = 6, 12 | String4 = 7, 13 | Map = 8, 14 | List = 9, 15 | StructBegin = 10, 16 | StructEnd = 11, 17 | Zero = 12, 18 | SimpleList = 13 19 | } 20 | } 21 | --------------------------------------------------------------------------------