Ejemplo n.º 1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MessageServer"/> class with routes accessible over HTTP
        /// for listing, reading, writing, updating and deleting messages.
        /// </summary>
        public MessageServer(IWebServer webServer)
        {
            _messages = new Dictionary <int, string>();
            _web      = webServer;
            _count    = 0;

            _web.RegisterStaticRoute("GET", "/messages", _ => Task.FromResult(new RestResponse(HttpStatusCode.OK, JsonConvert.SerializeObject(ListMessages()))));
            _web.RegisterStaticRoute("POST", "/messages", ctx => Task.FromResult(new RestResponse(HttpStatusCode.Created, JsonConvert.SerializeObject(AddMessage(ctx.Payload)))));
            _web.RegisterResourceRoute("PUT", "/messages/%", ctx =>
            {
                int id = ParseIntOrZero(ctx.Resources[0]);

                if (id <= 0)
                {
                    return(Task.FromResult(new RestResponse(HttpStatusCode.BadRequest, "Invalid message id.")));
                }

                bool created = UpdateMessage(id, ctx.Payload);
                return(Task.FromResult(new RestResponse(created ? HttpStatusCode.Created : HttpStatusCode.OK, string.Empty)));
            });
            _web.RegisterResourceRoute("DELETE", "/messages/%", ctx =>
            {
                int id = ParseIntOrZero(ctx.Resources[0]);

                if (id <= 0)
                {
                    return(Task.FromResult(new RestResponse(HttpStatusCode.BadRequest, "Invalid message id.")));
                }

                bool deleted = RemoveMessage(id);
                return(Task.FromResult(new RestResponse(deleted ? HttpStatusCode.OK : HttpStatusCode.NotFound, string.Empty)));
            });
            _web.RegisterResourceRoute("GET", "/messages/%", ctx =>
            {
                int id = ParseIntOrZero(ctx.Resources[0]);

                if (id <= 0)
                {
                    return(Task.FromResult(new RestResponse(HttpStatusCode.BadRequest, "Invalid message id.")));
                }

                var text = GetMessage(id);
                return(Task.FromResult(new RestResponse(text is null ? HttpStatusCode.NotFound : HttpStatusCode.OK,
                                                        text is null ? string.Empty : JsonConvert.SerializeObject(text))));
            });
Ejemplo n.º 2
0
        /// <summary>
        /// Registers necessary routes for executing MTCG.
        /// This method may only be called once per instance.
        /// </summary>
        public void Setup()
        {
            _server.AddScoreboard(nameof(HighestELO), new HighestELO());
            _server.AddScoreboard(nameof(LeastLosses), new LeastLosses());
            _server.AddScoreboard(nameof(MostWins), new MostWins());
            JsonConvert.DefaultSettings = () => new JsonSerializerSettings()
            {
                Converters = new List <JsonConverter> {
                    new Newtonsoft.Json.Converters.StringEnumConverter()
                }
            };

            // Register user
            _web.RegisterStaticRoute("POST", "/register", async ctx =>
            {
                if (!TryGetObject <UserCredentialsModel>(ctx, out var creds))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "User credentials not properly defined."));
                }

                var session = await _server.Register(creds.Username, creds.Password);

                if (session is null)
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "User already exists."));
                }

                return(new RestResponse(HttpStatusCode.OK, CreateHeader(("Authorization", session.Token.ToString("N"))), "Successfully registered account."));
            });

            // Login user
            _web.RegisterStaticRoute("POST", "/login", async ctx =>
            {
                if (!TryGetObject <UserCredentialsModel>(ctx, out var creds))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "User credentials not properly defined."));
                }

                var session = await _server.Login(creds.Username, creds.Password);

                if (session is null)
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "User was not found or wrong password."));
                }

                return(new RestResponse(HttpStatusCode.OK, CreateHeader(("Authorization", session.Token.ToString("N"))), "Successfully logged in."));
            });

            // Logout user
            _web.RegisterStaticRoute("POST", "/logout", ctx =>
            {
                if (!ctx.Headers.TryGetValue("Authorization", out var sessionStr))
                {
                    return(Task.FromResult(new RestResponse(HttpStatusCode.BadRequest, "No authorization supplied.")));
                }

                if (!Guid.TryParse(sessionStr, out var token))
                {
                    return(Task.FromResult(new RestResponse(HttpStatusCode.BadRequest, "Invalid authorization supplied.")));
                }

                if (!_server.Logout(new Session(token)))
                {
                    return(Task.FromResult(new RestResponse(HttpStatusCode.NotFound, "Not logged in.")));
                }

                return(Task.FromResult(new RestResponse(HttpStatusCode.OK, "Successfully logged out.")));
            });

            // Get player "profile"
            _web.RegisterResourceRoute("GET", "/profile/%", async ctx =>
            {
                var username = ctx.Resources[0];

                if (await _server.GetPlayer(username) is not Player player)
                {
                    return(new RestResponse(HttpStatusCode.NotFound, "Player was not found."));
                }

                return(new RestResponse(HttpStatusCode.OK, JsonConvert.SerializeObject(player)));
            });

            // Get own player "profile"
            _web.RegisterStaticRoute("GET", "/profile", async ctx =>
            {
                if (!ctx.Headers.TryGetValue("Authorization", out var sessionStr))
                {
                    return(new RestResponse(HttpStatusCode.Unauthorized, "No authorization supplied."));
                }

                if (!Guid.TryParse(sessionStr, out var token))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Invalid authorization supplied."));
                }

                if (await _server.GetPlayer(new Session(token)) is not Player player)
                {
                    return(new RestResponse(HttpStatusCode.Unauthorized, "Invalid session."));
                }

                return(new RestResponse(HttpStatusCode.OK, JsonConvert.SerializeObject(player)));
            });

            // Edit player "profile"
            _web.RegisterStaticRoute("POST", "/profile", async ctx =>
            {
                if (!ctx.Headers.TryGetValue("Authorization", out var sessionStr))
                {
                    return(new RestResponse(HttpStatusCode.Unauthorized, "No authorization supplied."));
                }

                if (!Guid.TryParse(sessionStr, out var token))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Invalid authorization supplied."));
                }

                if (!TryGetObject <EditPlayerModel>(ctx, out var editModel))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Invalid edit."));
                }

                if (!await _server.EditPlayer(new Session(token), editModel.Username, editModel.StatusText, editModel.EmoticonText, editModel.Password))
                {
                    return(new RestResponse(HttpStatusCode.Unauthorized, "Invalid session or invalid field length."));
                }

                return(new RestResponse(HttpStatusCode.OK, "Changes have been saved."));
            });

            // Get any player stack
            _web.RegisterResourceRoute("GET", "/profile/%/stack", async ctx =>
            {
                var username = ctx.Resources[0];

                if (await _server.GetPlayer(username) is Player player)
                {
                    return(new RestResponse(HttpStatusCode.OK, JsonConvert.SerializeObject(player.Stack)));
                }

                return(new RestResponse(HttpStatusCode.NotFound, "Player was not found."));
            });

            // Get any player deck
            _web.RegisterResourceRoute("GET", "/profile/%/deck", async ctx =>
            {
                var username = ctx.Resources[0];

                if (await _server.GetPlayer(username) is Player player)
                {
                    return(new RestResponse(HttpStatusCode.OK, JsonConvert.SerializeObject(player.Deck)));
                }

                return(new RestResponse(HttpStatusCode.NotFound, "Player was not found."));
            });

            // Get own stack
            _web.RegisterStaticRoute("GET", "/stack", async ctx =>
            {
                if (!ctx.Headers.TryGetValue("Authorization", out var sessionStr))
                {
                    return(new RestResponse(HttpStatusCode.Unauthorized, "No authorization supplied."));
                }

                if (!Guid.TryParse(sessionStr, out var token))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Invalid authorization supplied."));
                }

                if (await _server.GetPlayer(new Session(token)) is Player player)
                {
                    return(new RestResponse(HttpStatusCode.OK, JsonConvert.SerializeObject(player.Stack)));
                }

                return(new RestResponse(HttpStatusCode.Unauthorized, "Player not logged in."));
            });

            // Get own deck
            _web.RegisterStaticRoute("GET", "/deck", async ctx =>
            {
                if (!ctx.Headers.TryGetValue("Authorization", out var sessionStr))
                {
                    return(new RestResponse(HttpStatusCode.Unauthorized, "No authorization supplied."));
                }

                if (!Guid.TryParse(sessionStr, out var token))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Invalid authorization supplied."));
                }

                if (await _server.GetPlayer(new Session(token)) is Player player)
                {
                    return(new RestResponse(HttpStatusCode.OK, JsonConvert.SerializeObject(player.Deck)));
                }

                return(new RestResponse(HttpStatusCode.Unauthorized, "Player not logged in."));
            });

            // Edit deck
            _web.RegisterStaticRoute("POST", "/deck", async ctx =>
            {
                if (!ctx.Headers.TryGetValue("Authorization", out var sessionStr))
                {
                    return(new RestResponse(HttpStatusCode.Unauthorized, "No authorization supplied."));
                }

                if (!Guid.TryParse(sessionStr, out var token))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Invalid authorization supplied."));
                }

                if (!TryGetObject <Guid[]>(ctx, out var cardIds))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Invalid deck specification."));
                }

                if (await _server.SetDeck(new Session(token), cardIds))
                {
                    return(new RestResponse(HttpStatusCode.OK, "Successfully updated deck."));
                }

                return(new RestResponse(HttpStatusCode.BadRequest, "Invalid session, not exactly four cards or invalid card ID."));
            });

            // Battling
            _web.RegisterStaticRoute("POST", "/battle", async ctx =>
            {
                if (!ctx.Headers.TryGetValue("Authorization", out var sessionStr))
                {
                    return(new RestResponse(HttpStatusCode.Unauthorized, "No authorization supplied."));
                }

                if (!Guid.TryParse(sessionStr, out var token))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Invalid authorization supplied."));
                }

                if (await _server.InvokeBattle(new Session(token)) is not BattleResult result)
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Invalid session or invalid deck configuration."));
                }

                return(new RestResponse(HttpStatusCode.OK, JsonConvert.SerializeObject(result)));
            });

            // View card store ("trading")
            _web.RegisterStaticRoute("GET", "/store/cards", async _ =>
                                     new RestResponse(HttpStatusCode.OK, JsonConvert.SerializeObject(await _server.GetAvailableStoreCards())));

            // View card store ("trading") eligible entries
            _web.RegisterStaticRoute("GET", "/store/cards/eligible", async ctx =>
            {
                if (!ctx.Headers.TryGetValue("Authorization", out var sessionStr))
                {
                    return(new RestResponse(HttpStatusCode.Unauthorized, "No authorization supplied."));
                }

                if (!Guid.TryParse(sessionStr, out var token))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Invalid authorization supplied."));
                }

                if (!TryGetObject <Guid>(ctx, out var cardId))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Incorrectly formatted card ID."));
                }

                var result = await _server.GetEligibleStoreCards(new Session(token), cardId);

                if (result is null)
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Invalid session, invalid card or card not in stack"));
                }

                return(new RestResponse(HttpStatusCode.OK, JsonConvert.SerializeObject(result)));
            });

            // Push to card store ("trading push")
            _web.RegisterStaticRoute("POST", "/store/cards/new", async ctx =>
            {
                if (!ctx.Headers.TryGetValue("Authorization", out var sessionStr))
                {
                    return(new RestResponse(HttpStatusCode.Unauthorized, "No authorization supplied."));
                }

                if (!Guid.TryParse(sessionStr, out var token))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Invalid authorization supplied."));
                }

                if (!TryGetObject <PushCardStoreModel>(ctx, out var pushModel))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Invalid specification."));
                }

                List <ICardRequirement> translatedReqs = new(pushModel.Requirements.Length);

                foreach (var req in pushModel.Requirements)
                {
                    switch (req.RequirementType)
                    {
                    case RequirementType.ElementType when req.RequiredElement.HasValue:
                        translatedReqs.Add(new ElementTypeRequirement()
                        {
                            Type = req.RequiredElement.Value
                        });
                        break;

                    case RequirementType.IsMonsterCard:
                        translatedReqs.Add(new IsMonsterCardRequirement());
                        break;

                    case RequirementType.IsSpellCard:
                        translatedReqs.Add(new IsSpellCardRequirement());
                        break;

                    case RequirementType.MinimumDamage when req.MinimumDamage.HasValue:
                        translatedReqs.Add(new MinimumDamageRequirement()
                        {
                            MinimumDamage = req.MinimumDamage.Value
                        });
                        break;

                    default:
                        return(new RestResponse(HttpStatusCode.BadRequest, "Unknown requirement type or missing value."));
                    }
                }

                if (!await _server.PushCardToStore(new Session(token), pushModel.CardId, translatedReqs))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Invalid session or card ID."));
                }

                return(new RestResponse(HttpStatusCode.Created, "Successfully pushed card to store: " + pushModel.CardId));
            });

            // Trade with card store ("trading")
            _web.RegisterStaticRoute("POST", "/store/cards/trade", async ctx =>
            {
                if (!ctx.Headers.TryGetValue("Authorization", out var sessionStr))
                {
                    return(new RestResponse(HttpStatusCode.Unauthorized, "No authorization supplied."));
                }

                if (!Guid.TryParse(sessionStr, out var token))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Invalid authorization supplied."));
                }

                if (!TryGetObject <CardTradeModel>(ctx, out var tradeModel))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Incorrectly formatted trade model."));
                }

                if (!await _server.TradeCards(new Session(token), tradeModel.OwnCard, tradeModel.OtherCard))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Invalid session or card specifiction."));
                }

                return(new RestResponse(HttpStatusCode.OK, "Successfully traded cards."));
            });

            // Get packages
            _web.RegisterStaticRoute("GET", "/store/packages", async _ =>
                                     new RestResponse(HttpStatusCode.OK, JsonConvert.SerializeObject(await _server.GetAllPackages())));

            // Get affordable packages (max price in route)
            _web.RegisterResourceRoute("GET", "/store/packages/max/%", async ctx =>
            {
                if (!int.TryParse(ctx.Resources[0], out var maxPrice))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Invalid maximum price."));
                }

                return(new RestResponse(HttpStatusCode.OK, JsonConvert.SerializeObject(await _server.GetAffordablePackages(maxPrice))));
            });

            // Get affordable packages for player
            _web.RegisterStaticRoute("GET", "/store/packages/affordable", async ctx =>
            {
                if (!ctx.Headers.TryGetValue("Authorization", out var sessionStr))
                {
                    return(new RestResponse(HttpStatusCode.Unauthorized, "No authorization supplied."));
                }

                if (!Guid.TryParse(sessionStr, out var token))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Invalid authorization supplied."));
                }

                var result = await _server.GetAffordablePackages(new Session(token));

                if (result is null)
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Invalid session."));
                }

                return(new RestResponse(HttpStatusCode.OK, JsonConvert.SerializeObject(result)));
            });

            // Push to package store
            _web.RegisterStaticRoute("POST", "/store/packages", async ctx =>
            {
                if (!ctx.Headers.TryGetValue("Authorization", out var sessionStr))
                {
                    return(new RestResponse(HttpStatusCode.Unauthorized, "No authorization supplied."));
                }

                if (!Guid.TryParse(sessionStr, out var token))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Invalid authorization supplied."));
                }

                if (!TryGetObject <PushCardPackageModel>(ctx, out var pushModel))
                {
                    return(new RestResponse(HttpStatusCode.BadRequest, "Invalid package."));
                }

                List <ICard> translatedCards = new(pushModel.Cards.Length);
                var packageId = Guid.NewGuid();

                foreach (var card in pushModel.Cards)
                {
                    try
                    {
                        translatedCards.Add(card.CardType switch
                        {
                            CardType.Dragon => new Dragon      {
                                Id = Guid.NewGuid(), Damage = card.Damage
                            },
                            CardType.FireElf => new FireElf     {
                                Id = Guid.NewGuid(), Damage = card.Damage
                            },
                            CardType.Goblin => new Goblin      {
                                Id = Guid.NewGuid(), Damage = card.Damage
                            },
                            CardType.Knight => new Knight      {
                                Id = Guid.NewGuid(), Damage = card.Damage
                            },
                            CardType.Kraken => new Kraken      {
                                Id = Guid.NewGuid(), Damage = card.Damage
                            },
                            CardType.Ork => new Ork         {
                                Id = Guid.NewGuid(), Damage = card.Damage
                            },
                            CardType.Wizard => new Wizard      {
                                Id = Guid.NewGuid(), Damage = card.Damage
                            },
                            CardType.NormalSpell => new NormalSpell {
                                Id = Guid.NewGuid(), Damage = card.Damage
                            },
                            CardType.WaterSpell => new WaterSpell  {
                                Id = Guid.NewGuid(), Damage = card.Damage
                            },
                            CardType.FireSpell => new FireSpell   {
                                Id = Guid.NewGuid(), Damage = card.Damage
                            },
                            _ => throw new ArgumentOutOfRangeException()
                        });
                    }
                    catch (ArgumentOutOfRangeException)
                    {
                        return(new RestResponse(HttpStatusCode.BadRequest, "Unknown card type: " + card.CardType));
                    }
                }