Esempio n. 1
0
        static void Main(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException += (_, eventArgs) =>
            {
                var exception = eventArgs.ExceptionObject as Exception;

                string message = string.Format("Unhandled exception: {0}: {1} \r\n{2}", exception.GetType().ToString(),
                                               exception.Message, exception.StackTrace);

                LogTo.Fatal(message);
                HipchatSender.SendNotification("Server errors", message, RoomColors.Random);
            };

            try
            {
                LogTo.Debug("======================= STARTING ==========================");

                IKernel kernel = new StandardKernel();

                // Factories
                kernel.Bind <IChannelHandlerFactory>().ToFactory();
                kernel.Bind <IChatProviderFactory>().ToFactory();

                // Singletons
                kernel.Bind <RedisProvider>().ToSelf().InSingletonScope();

                // Standard lifetime
                kernel.Bind <IPlaylistProvider>().To <SortedPlaylistProvider>();
                kernel.Bind <IMQTTSettings>().To <ServerMqttSettings>();

                var server = kernel.Get <Server>();
                server.Run();

                var heartbeat = TimeSpan.FromMinutes(3);
                while (true)
                {
                    File.WriteAllText("sovndserver.heartbeat", Time.Timestamp().ToString());
                    Thread.Sleep(heartbeat);
                }
            }
            finally
            {
                LogTo.Debug("========================= DEAD ============================");
            }
        }
Esempio n. 2
0
        public Server(IMQTTSettings settings, IChannelHandlerFactory chf, ServerSpotifyAuth spot, RedisProvider redis)
            : base(settings.Broker, settings.Port, settings.Username, settings.Password)
        {
            _spot            = spot;
            _redisconnection = redis.redis;
            _redis           = _redisconnection.GetDatabase();

            LogTo.Trace("Initializing routes");

            //////
            // User messages
            //////
            ///

            // Handle user-channel interaction
            On["/user/{username}/{channel}/songs/{songid}"] = msg =>
            {
                switch ((string)msg.Message)
                {
                case "vote":
                    AddVote(msg.channel, msg.songid, msg.username);
                    break;

                case "unvote":
                    RemoveVote(msg.channel, msg.songid, msg.username);
                    break;

                case "report":
                    ReportSong(msg.channel, msg.songid, msg.username);
                    break;

                case "remove":
                    RemoveSong(msg.channel, msg.songid, msg.username);
                    break;

                case "block":
                    BlockSong(msg.channel, msg.songid, msg.username);
                    break;

                default:
                    LogTo.Warn("[{0}] Invalid command: {1}: {2}, by {3}", (string)msg.channel, (string)msg.Topic, (string)msg.Message, (string)msg.username);
                    break;
                }
            };

            // Handle channel registration
            On["/user/{username}/register/{channel}"] = _ =>
            {
                // TODO Separate channel name from ID

                Channel channel = JsonConvert.DeserializeObject <Channel>(_.Message);

                if (channel == null ||
                    string.IsNullOrWhiteSpace(channel.Name))
                {
                    LogTo.Warn("Rejected invalid channel JSON from {0} for channel {1}: {2}", (string)_.username, (string)_.channel, (string)_.Message);
                    return;
                }

                LogTo.Info("[{0}] {1} sent channel data: {2}", (string)_.channel, (string)_.username, (string)_.Message);

                if (!_redis.KeyExists(GetChannelNameID(_.channel)))
                {
                    // Channel doesn't exist yet
                    LogTo.Info("[{0}] Setting up new channel for {1}", (string)_.channel, (string)_.username);

                    _redis.StringSet(GetChannelNameID(_.channel), channel.Name);
                    _redis.StringSet(GetChannelDescriptionID(_.channel), channel.Description);
                    _redis.SetAdd(GetChannelModeratorID(_.channel), _.username);
                }
                else
                {
                    // Channel exists

                    if (!_redis.SetContains(GetChannelModeratorID(_.channel), _.username))
                    {
                        LogTo.Error("[{0}] Error: User {1} not a moderator of channel", (string)_.channel, (string)_.username);
                        return;
                    }

                    LogTo.Info("[{0}] changing existing channel for {1}", (string)_.channel, (string)_.username);

                    _redis.StringSet(GetChannelNameID(_.channel), channel.Name);
                    _redis.StringSet(GetChannelDescriptionID(_.channel), channel.Description);
                }

                Publish(string.Format("/{0}/info", _.channel), _.Message, true);
            };

            // Handle user chat messages
            On["/user/{username}/{channel}/chat"] = _ =>
            {
                LogTo.Trace("{0}->{1}: {2}", (string)_.username, (string)_.channel, (string)_.Message);

                // TODO [LOW] Allow moderators to mute users

                if (channels.ContainsKey(_.channel))
                {
                    var topic   = string.Format("/{0}/chat", _.channel);
                    var message = new ChatMessage
                    {
                        message  = _.Message,
                        username = _.username,
                        time     = Time.Timestamp()
                    };
                    var messageJson = JsonConvert.SerializeObject(message);
                    Publish(topic, messageJson);
                    HipchatSender.SendNotification(_.channel, string.Format("{0}: {1}", message.username, message.message), RoomColors.Gray);
                }
                else
                {
                    LogTo.Debug("Chat was for invalid channel");
                }
            };

            //////
            // Channel messages
            //////
            // TODO: This should be separate from above

            // Handle channel info
            On["/{channel}/info"] = _ =>
            {
                LogTo.Info("[{0}] Got info: {1}", (string)_.channel, (string)_.Message);

                Channel channel = JsonConvert.DeserializeObject <Channel>(_.Message);

                if (!channels.ContainsKey(_.channel))
                {
                    ChannelHandler channelHandler = chf.CreateChannelHandler(_.channel);
                    channelHandler.Subscribe();
                    channels[_.channel] = channelHandler;
                    StartChannelScheduler(channelHandler);
                }
            };
        }