コード例 #1
0
        private (Bot?bot, BotInfo?info) InstantiateNewBot(ConfBot config)
        {
            lock (lockObj)
            {
                if (!string.IsNullOrEmpty(config.Name))
                {
                    var maybeBot = GetBotSave(config.Name);
                    if (maybeBot != null)
                    {
                        return(null, maybeBot.GetInfo());
                    }
                }

                var id = GetFreeId();
                if (id == null)
                {
                    return(null, null);                      // "BotManager is shutting down"
                }
                var botInjector = new BotInjector(coreInjector);
                botInjector.AddModule(botInjector);
                botInjector.AddModule(new Id(id.Value));
                botInjector.AddModule(config);
                if (!botInjector.TryCreate <Bot>(out var bot))
                {
                    return(null, null);                      // "Failed to create new Bot"
                }
                InsertBot(bot);
                return(bot, null);
            }
        }
コード例 #2
0
 public Voting(Player player, Ts3Client client, TsFullClient ts3FullClient, ConfBot config)
 {
     this.player        = player;
     this.client        = client;
     this.config        = config;
     this.ts3FullClient = ts3FullClient;
 }
コード例 #3
0
        public Player(ConfBot config, Id id)
        {
            FfmpegProducer = new FfmpegProducer(config.GetParent().Tools.Ffmpeg, id);
            WebSocketPipe  = new WebSocketPipe();
            StallCheckPipe = new StallCheckPipe();
            VolumePipe     = new VolumePipe();
            Volume         = config.Audio.Volume.Default;
            EncoderPipe    = new EncoderPipe(SendCodec)
            {
                Bitrate = ScaleBitrate(config.Audio.Bitrate)
            };
            EncoderPipeHighQuality = new EncoderPipe(Codec.OpusMusic)
            {
                Bitrate = 192000
            };
            TimePipe = new PreciseTimedPipe {
                ReadBufferSize = EncoderPipe.PacketSize
            };
            TimePipe.Initialize(EncoderPipe, id);
            MergePipe    = new PassiveMergePipe();
            SplitterPipe = new PassiveSplitterPipe();

            config.Audio.Bitrate.Changed += (s, e) => EncoderPipe.Bitrate = ScaleBitrate(e.NewValue);

            MergePipe.Into(TimePipe).Chain <CheckActivePipe>().Chain(SplitterPipe);
            SplitterPipe.Chain(EncoderPipeHighQuality).Chain(WebSocketPipe);
            SplitterPipe.Chain(StallCheckPipe).Chain(VolumePipe).Chain(EncoderPipe);
        }
コード例 #4
0
 public PlayManager(ConfBot config, IPlayerConnection playerConnection, PlaylistManager playlistManager, ResourceFactory resourceFactory)
 {
     confBot = config;
     this.playerConnection = playerConnection;
     this.playlistManager  = playlistManager;
     this.resourceFactory  = resourceFactory;
 }
コード例 #5
0
 public PlayManager(ConfBot config, Player playerConnection, PlaylistManager playlistManager, ResourceResolver resourceResolver)
 {
     confBot = config;
     this.playerConnection = playerConnection;
     this.playlistManager  = playlistManager;
     this.resourceResolver = resourceResolver;
 }
コード例 #6
0
 public PlaylistIO(ConfBot confBot)
 {
     this.confBot  = confBot;
     playlistCache = new LruCache <string, Playlist>(16);
     Util.Init(out playlistInfo);
     Util.Init(out dirtyList);
 }
コード例 #7
0
        public static string ExecuteTryCatch(
            ConfBot config, bool answer, Func <string> action, Action <string> errorHandler)
        {
            try {
                return(action());
            } catch (CommandException ex) {
                NLog.LogLevel commandErrorLevel = answer ? NLog.LogLevel.Debug : NLog.LogLevel.Warn;
                Log.Log(commandErrorLevel, ex, "Command Error ({0})", ex.Message);
                if (answer)
                {
                    errorHandler(TextMod.Format(config.Commands.Color,
                                                "Error: {0}".Mod().Color(Color.Red).Bold(),
                                                ex.Message));
                }
            } catch (Exception ex) {
                Log.Error(ex, "Unexpected command error: {0}", ex.UnrollException());
                if (answer)
                {
                    errorHandler(TextMod.Format(config.Commands.Color,
                                                "An unexpected error occured: {0}".Mod().Color(Color.Red).Bold(), ex.Message));
                }
            }

            return(null);
        }
コード例 #8
0
ファイル: PlayManager.cs プロジェクト: ts3-world/TS3AudioBot
 public PlayManager(ConfBot config, Player playerConnection, PlaylistManager playlistManager, ResolveContext resourceResolver, Stats stats)
 {
     confBot = config;
     this.playerConnection = playerConnection;
     this.playlistManager  = playlistManager;
     this.resourceResolver = resourceResolver;
     this.stats            = stats;
 }
コード例 #9
0
ファイル: MediaResolver.cs プロジェクト: Tommmciu/TS3AudioBot
 private R <ResData, LocalStr> ValidateFromString(ConfBot config, string uriStr)
 {
     if (TryGetUri(config, uriStr).GetOk(out var uri))
     {
         return(ValidateUri(uri));
     }
     return(new LocalStr(strings.error_media_invalid_uri));
 }
コード例 #10
0
 public StartSongTask(ResolveContext resourceResolver, Player player, ConfBot config, object playManagerLock, QueueItem queueItem)
 {
     this.resourceResolver = resourceResolver;
     this.player           = player;
     this.config           = config;
     this.playManagerLock  = playManagerLock;
     QueueItem             = queueItem;
 }
コード例 #11
0
ファイル: Bot.cs プロジェクト: xThunderbolt/TS3AudioBot
 public Bot(Id id, ConfBot config, BotInjector injector, ResourceFactory resourceFactory, CommandManager commandManager)
 {
     this.Id              = id;
     this.config          = config;
     this.Injector        = injector;
     this.resourceFactory = resourceFactory;
     this.commandManager  = commandManager;
 }
コード例 #12
0
ファイル: PlayManager.cs プロジェクト: jwiesler/TS3AudioBot
 // Needed for the injector cancer
 public PlayManager(
     ConfBot config, Player playerConnection, ResolveContext resourceResolver, PlaylistManager playlistManager)
     : this(playerConnection, playlistManager)
 {
     taskHost = new StartSongTaskHost(
         item =>
         new StartSongTaskHandler(new StartSongTask(resourceResolver, playerConnection, config.Audio.Volume,
                                                    Lock, item))
         );
     Init();
 }
コード例 #13
0
        public Ts3Client(ConfBot config, TsFullClient ts3FullClient, Id id)
        {
            this.id = id;

            this.ts3FullClient = ts3FullClient;
            ts3FullClient.OnEachTextMessage += ExtendedTextMessage;
            ts3FullClient.OnErrorEvent      += TsFullClient_OnErrorEvent;
            ts3FullClient.OnConnected       += TsFullClient_OnConnected;
            ts3FullClient.OnDisconnected    += TsFullClient_OnDisconnected;
            ts3FullClient.OnEachClientMoved += (s, e) =>
            {
                UpdateReconnectChannel(e.ClientId, e.TargetChannelId);
                if (AloneRecheckRequired(e.ClientId, e.TargetChannelId))
                {
                    IsAloneRecheck();
                }
            };
            ts3FullClient.OnEachClientEnterView += (s, e) =>
            {
                UpdateReconnectChannel(e.ClientId, e.TargetChannelId);
                if (AloneRecheckRequired(e.ClientId, e.TargetChannelId))
                {
                    IsAloneRecheck();
                }
                else if (AloneRecheckRequired(e.ClientId, e.SourceChannelId))
                {
                    IsAloneRecheck();
                }
            };
            ts3FullClient.OnEachClientLeftView += (s, e) =>
            {
                UpdateReconnectChannel(e.ClientId, e.TargetChannelId);
                if (AloneRecheckRequired(e.ClientId, e.TargetChannelId))
                {
                    IsAloneRecheck();
                }
                else if (AloneRecheckRequired(e.ClientId, e.SourceChannelId))
                {
                    IsAloneRecheck();
                }
            };

            this.config = config;
            identity    = null;
        }
コード例 #14
0
        public R <BotInfo, string> RunBot(ConfBot config)
        {
            Bot bot;

            lock (lockObj)
            {
                if (!string.IsNullOrEmpty(config.Name))
                {
                    bot = GetBotSave(config.Name);
                    if (bot != null)
                    {
                        return(bot.GetInfo());
                    }
                }

                var id = GetFreeId();
                if (id == null)
                {
                    return("BotManager is shutting down");
                }

                var botInjector = new BotInjector(coreInjector);
                botInjector.AddModule(botInjector);
                botInjector.AddModule(new TS3Client.Helper.Id(id.Value));
                botInjector.AddModule(config);
                if (!botInjector.TryCreate(out bot))
                {
                    return("Failed to create new Bot");
                }
                InsertBot(bot);
            }

            lock (bot.SyncRoot)
            {
                var initializeResult = bot.InitializeBot();
                if (!initializeResult.Ok)
                {
                    StopBot(bot);
                    return($"Bot failed to connect ({initializeResult.Error})");
                }
            }
            return(bot.GetInfo());
        }
コード例 #15
0
        public PlayManager(ConfBot config, Player playerConnection, ResolveContext resourceResolver, Stats stats, PlaylistManager playlistManager)
        {
            confBot = config;
            this.playerConnection = playerConnection;
            this.resourceResolver = resourceResolver;
            this.stats            = stats;
            this.playlistManager  = playlistManager;

            playerConnection.FfmpegProducer.OnSongLengthParsed += (sender, args) => {
                lock (Lock) {
                    if (Current == null)
                    {
                        return;
                    }
                    Log.Info("Preparing song analyzer... (OnSongLengthParsed)");
                    Current.UpdateStartAnalyzeTime(GetAnalyzeTaskStartTime());
                }
            };
        }
コード例 #16
0
ファイル: MediaResolver.cs プロジェクト: Tommmciu/TS3AudioBot
        private R <Uri, LocalStr> TryGetUri(ConfBot conf, string uri)
        {
            if (Uri.TryCreate(uri, UriKind.Absolute, out Uri uriResult))
            {
                return(uriResult);
            }
            else
            {
                Log.Trace("Finding media path: '{0}'", uri);

                var file =
                    TryInPath(Path.Combine(conf.LocalConfigDir, BotPaths.Music), uri)
                    ?? TryInPath(conf.GetParent().Factories.Media.Path.Value, uri);

                if (file == null)
                {
                    return(new LocalStr(strings.error_media_file_not_found));
                }
                return(file);
            }
        }
コード例 #17
0
ファイル: BotManager.cs プロジェクト: treewords/TS3AudioBot
        public R <BotInfo, string> RunBot(ConfBot config, string name = null)
        {
            var bot = new Bot(config)
            {
                Injector = CoreInjector.CloneRealm <BotInjector>(), Name = name
            };

            if (!CoreInjector.TryInject(bot))
            {
                Log.Warn("Partial bot dependency loaded only");
            }

            lock (bot.SyncRoot)
            {
                var initializeResult = bot.InitializeBot();
                var removeBot        = false;
                if (initializeResult.Ok)
                {
                    lock (lockObj)
                    {
                        if (!InsertIntoFreeId(bot))
                        {
                            removeBot = true;
                        }
                    }
                }
                else
                {
                    return($"Bot failed to connect ({initializeResult.Error})");
                }

                if (removeBot)
                {
                    StopBot(bot);
                    return("BotManager is shutting down");
                }
            }
            return(bot.GetInfo());
        }
コード例 #18
0
        public Player(ConfRoot confRoot, ConfBot config, DedicatedTaskScheduler scheduler, Id id)
        {
            this.scheduler = scheduler;

            FfmpegProducer = new FfmpegProducer(confRoot.Tools.Ffmpeg, scheduler, id);
            StallCheckPipe = new StallCheckPipe();
            VolumePipe     = new VolumePipe();
            Volume         = config.Audio.Volume.Default;
            EncoderPipe    = new EncoderPipe(SendCodec)
            {
                Bitrate = ScaleBitrate(config.Audio.Bitrate)
            };
            TimePipe = new PreciseTimedPipe(EncoderPipe, id)
            {
                ReadBufferSize = EncoderPipe.PacketSize
            };
            MergePipe = new PassiveMergePipe();

            config.Audio.Bitrate.Changed += (s, e) => EncoderPipe.Bitrate = ScaleBitrate(e.NewValue);

            MergePipe.Into(TimePipe).Chain <CheckActivePipe>().Chain(StallCheckPipe).Chain(VolumePipe).Chain(EncoderPipe);
        }
コード例 #19
0
        public Ts3Client(ConfBot config)
        {
            Util.Init(out clientDbNames);
            Util.Init(out clientbuffer);

            TsFullClient = new Ts3FullClient(EventDispatchType.DoubleThread);
            TsFullClient.OnClientLeftView  += ExtendedClientLeftView;
            TsFullClient.OnClientEnterView += ExtendedClientEnterView;
            TsFullClient.OnTextMessage     += ExtendedTextMessage;
            TsFullClient.OnErrorEvent      += TsFullClient_OnErrorEvent;
            TsFullClient.OnConnected       += TsFullClient_OnConnected;
            TsFullClient.OnDisconnected    += TsFullClient_OnDisconnected;

            int ScaleBitrate(int value) => Math.Min(Math.Max(1, value), 255) * 1000;

            this.config = config;
            this.config.Audio.Bitrate.Changed += (s, e) => encoderPipe.Bitrate = ScaleBitrate(e.NewValue);

            ffmpegProducer = new FfmpegProducer(config.GetParent().Tools.Ffmpeg);
            stallCheckPipe = new StallCheckPipe();
            volumePipe     = new VolumePipe();
            Volume         = config.Audio.Volume.Default;
            encoderPipe    = new EncoderPipe(SendCodec)
            {
                Bitrate = ScaleBitrate(config.Audio.Bitrate)
            };
            timePipe = new PreciseTimedPipe {
                ReadBufferSize = encoderPipe.PacketSize
            };
            timePipe.Initialize(encoderPipe);
            TargetPipe = new CustomTargetPipe(TsFullClient);
            mergePipe  = new PassiveMergePipe();

            mergePipe.Add(ffmpegProducer);
            mergePipe.Into(timePipe).Chain <CheckActivePipe>().Chain(stallCheckPipe).Chain(volumePipe).Chain(encoderPipe).Chain(TargetPipe);

            identity = null;
        }
コード例 #20
0
ファイル: Ts3Client.cs プロジェクト: xThunderbolt/TS3AudioBot
        public Ts3Client(ConfBot config, Ts3FullClient tsFullClient, Id id)
        {
            this.id = id;
            Util.Init(out clientDbNames);
            Util.Init(out clientbuffer);
            dbIdCache = new LruCache <string, ulong>(1024);

            this.tsFullClient = tsFullClient;
            tsFullClient.OnEachTextMessage += ExtendedTextMessage;
            tsFullClient.OnErrorEvent      += TsFullClient_OnErrorEvent;
            tsFullClient.OnConnected       += TsFullClient_OnConnected;
            tsFullClient.OnDisconnected    += TsFullClient_OnDisconnected;

            int ScaleBitrate(int value) => Util.Clamp(value, 1, 255) * 1000;

            this.config = config;
            this.config.Audio.Bitrate.Changed += (s, e) => encoderPipe.Bitrate = ScaleBitrate(e.NewValue);

            ffmpegProducer = new FfmpegProducer(config.GetParent().Tools.Ffmpeg, id);
            stallCheckPipe = new StallCheckPipe();
            volumePipe     = new VolumePipe();
            Volume         = config.Audio.Volume.Default;
            encoderPipe    = new EncoderPipe(SendCodec)
            {
                Bitrate = ScaleBitrate(config.Audio.Bitrate)
            };
            timePipe = new PreciseTimedPipe {
                ReadBufferSize = encoderPipe.PacketSize
            };
            timePipe.Initialize(encoderPipe, id);
            TargetPipe = new CustomTargetPipe(tsFullClient);
            mergePipe  = new PassiveMergePipe();

            mergePipe.Add(ffmpegProducer);
            mergePipe.Into(timePipe).Chain <CheckActivePipe>().Chain(stallCheckPipe).Chain(volumePipe).Chain(encoderPipe).Chain(TargetPipe);

            identity = null;
        }
コード例 #21
0
        private Uri GetUri(ConfBot conf, string uri)
        {
            if (Uri.TryCreate(uri, UriKind.Absolute, out Uri? uriResult))
            {
                return(uriResult);
            }
            else
            {
                Log.Trace("Finding media path: '{0}'", uri);

                Uri?file = null;
                if (conf.LocalConfigDir != null)
                {
                    file ??= TryInPath(Path.Combine(conf.LocalConfigDir, BotPaths.Music), uri);
                }
                file ??= TryInPath(conf.GetParent().Factories.Media.Path.Value, uri);

                if (file is null)
                {
                    throw Error.LocalStr(strings.error_media_file_not_found);
                }
                return(file);
            }
        }
コード例 #22
0
        public async Task <R <BotInfo, string> > RunBot(ConfBot config)
        {
            var(bot, info) = InstantiateNewBot(config);
            if (info != null)
            {
                return(info);
            }

            if (bot is null)
            {
                return("Failed to create new Bot");
            }

            return(await bot.Scheduler.InvokeAsync <R <BotInfo, string> >(async() =>
            {
                var initializeResult = await bot.Run();
                if (!initializeResult.Ok)
                {
                    await StopBot(bot);
                    return $"Bot failed to initialize ({initializeResult.Error})";
                }
                return bot.GetInfo();
            }));
        }
コード例 #23
0
ファイル: Bot.cs プロジェクト: Tommmciu/TS3AudioBot
 public Bot(Id id, ConfBot config, BotInjector injector)
 {
     this.Id       = id;
     this.config   = config;
     this.Injector = injector;
 }
コード例 #24
0
 public PlaylistIO(ConfBot confBot)
 {
     this.confBot = confBot;
     ReloadFolder();
 }
コード例 #25
0
ファイル: PlaylistIO.cs プロジェクト: jwiesler/TS3AudioBot
 public PlaylistIO(ConfBot confBot)
 {
     this.confBot = confBot;
 }
コード例 #26
0
 public Bot(ConfBot config, BotInjector injector)
 {
     this.config   = config;
     this.Injector = injector;
 }
コード例 #27
0
        public Bot(Id id, ConfBot config, BotInjector injector)
        {
            this.Id       = id;
            this.config   = config;
            this.Injector = injector;

            // Registering config changes
            config.Language.Changed += async(s, e) =>
            {
                var langResult = await localization.LoadLanguage(e.NewValue, true);

                if (!langResult.Ok)
                {
                    Log.Error("Failed to load language file ({0})", langResult.Error);
                }
            };
            config.Events.IdleDelay.Changed += (s, e) => EnableIdleTickWorker();
            config.Events.OnIdle.Changed    += (s, e) => EnableIdleTickWorker();

            var builder = new DependencyBuilder(Injector);

            Injector.HideParentModule <CommandManager>();
            Injector.HideParentModule <DedicatedTaskScheduler>();
            Injector.AddModule(this);
            Injector.AddModule(config);
            Injector.AddModule(Injector);
            Injector.AddModule(config.Playlists);
            Injector.AddModule(config.History);
            Injector.AddModule(Id);
            builder.RequestModule <PlaylistIO>();
            builder.RequestModule <PlaylistManager>();
            builder.RequestModule <DedicatedTaskScheduler>();
            builder.RequestModule <TsFullClient>();
            builder.RequestModule <TsBaseFunctions, TsFullClient>();
            builder.RequestModule <Ts3Client>();
            builder.RequestModule <Player>();
            builder.RequestModule <CustomTargetPipe>();
            builder.RequestModule <IVoiceTarget, CustomTargetPipe>();
            builder.RequestModule <SessionManager>();
            builder.RequestModule <ResolveContext>();
            builder.RequestModule <CommandManager>();
            builder.RequestModule <LocalizationManager>();
            if (config.History.Enabled)
            {
                builder.RequestModule <HistoryManager>();
            }
            builder.RequestModule <PlayManager>();

            if (!builder.Build())
            {
                Log.Error("Missing bot module dependency");
                throw new Exception("Could not load all bot modules");
            }
            Injector.ClearHiddenParentModules();

            resourceResolver = Injector.GetModuleOrThrow <ResolveContext>();
            ts3FullClient    = Injector.GetModuleOrThrow <TsFullClient>();
            ts3client        = Injector.GetModuleOrThrow <Ts3Client>();
            player           = Injector.GetModuleOrThrow <Player>();
            Scheduler        = Injector.GetModuleOrThrow <DedicatedTaskScheduler>();
            var customTarget = Injector.GetModuleOrThrow <CustomTargetPipe>();

            player.SetTarget(customTarget);
            Injector.AddModule(ts3FullClient.Book);
            playManager    = Injector.GetModuleOrThrow <PlayManager>();
            targetManager  = Injector.GetModuleOrThrow <IVoiceTarget>();
            sessionManager = Injector.GetModuleOrThrow <SessionManager>();
            stats          = Injector.GetModuleOrThrow <Stats>();
            var commandManager = Injector.GetModuleOrThrow <CommandManager>();

            localization = Injector.GetModuleOrThrow <LocalizationManager>();

            idleTickWorker = Scheduler.Invoke(() => Scheduler.CreateTimer(OnIdle, TimeSpan.MaxValue, false)).Result;

            player.OnSongEnd     += playManager.SongStoppedEvent;
            player.OnSongUpdated += (s, e) => playManager.Update(e);
            // Update idle status events
            playManager.BeforeResourceStarted += (s, e) => { DisableIdleTickWorker(); return(Task.CompletedTask); };
            playManager.PlaybackStopped       += (s, e) => { EnableIdleTickWorker(); return(Task.CompletedTask); };
            // Used for custom scripts, like voice_mode, onsongstart
            playManager.BeforeResourceStarted += BeforeResourceStarted;
            playManager.AfterResourceStarted  += AfterResourceStarted;
            // Update the own status text to the current song title
            playManager.AfterResourceStarted += (s, e) => UpdateBotStatus();
            playManager.PlaybackStopped      += (s, e) => UpdateBotStatus();
            playManager.OnResourceUpdated    += (s, e) => UpdateBotStatus();
            // Log our resource in the history
            if (Injector.TryGet <HistoryManager>(out var historyManager))
            {
                playManager.AfterResourceStarted += (s, e) =>
                {
                    if (e.PlayInfo != null)
                    {
                        historyManager.LogAudioResource(new HistorySaveData(e.PlayResource.AudioResource, e.PlayInfo.ResourceOwnerUid));
                    }
                    return(Task.CompletedTask);
                }
            }
            ;
            // Update our thumbnail
            playManager.AfterResourceStarted += (s, e) => GenerateStatusImage(true, e);
            playManager.PlaybackStopped      += (s, e) => GenerateStatusImage(false, null);
            // Stats
            playManager.AfterResourceStarted += (s, e) => { stats.TrackSongStart(Id, e.ResourceData.AudioType); return(Task.CompletedTask); };
            playManager.ResourceStopped      += (s, e) => { stats.TrackSongStop(Id); return(Task.CompletedTask); };
            // Register callback for all messages happening
            ts3client.OnMessageReceived += OnMessageReceived;
            // Register callback to remove open private sessions, when user disconnects
            ts3FullClient.OnEachClientLeftView += OnClientLeftView;
            ts3client.OnBotConnected           += OnBotConnected;
            ts3client.OnBotDisconnected        += OnBotDisconnected;
            ts3client.OnBotStoppedReconnecting += OnBotStoppedReconnecting;
            // Alone mode
            ts3client.OnAloneChanged += OnAloneChanged;
            ts3client.OnAloneChanged += (s, e) => { customTarget.Alone = e.Alone; return(Task.CompletedTask); };
            // Whisper stall
            ts3client.OnWhisperNoTarget += (s, e) => player.SetStall();

            commandManager.RegisterCollection(MainCommands.Bag);
            // TODO remove after plugin rework
            var pluginManager = Injector.GetModuleOrThrow <PluginManager>();

            foreach (var plugin in pluginManager.Plugins)
            {
                if (plugin.Type == PluginType.CorePlugin || plugin.Type == PluginType.Commands)
                {
                    commandManager.RegisterCollection(plugin.CorePlugin.Bag);
                }
            }
            // Restore all alias from the config
            foreach (var alias in config.Commands.Alias.GetAllItems())
            {
                commandManager.RegisterAlias(alias.Key, alias.Value).UnwrapToLog(Log);
            }
        }
コード例 #28
0
        private Task <ResData> ValidateFromString(ConfBot config, string uriStr)
        {
            var uri = GetUri(config, uriStr);

            return(ValidateUri(uri));
        }
コード例 #29
0
ファイル: ResolveContext.cs プロジェクト: yakMM/TS3AudioBot
 public ResolveContext(ResourceResolver resolver, ConfBot config)
 {
     Resolver = resolver;
     Config   = config;
 }
コード例 #30
0
 public Bot(ConfBot config)
 {
     this.config = config;
 }