You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
7.0 KiB
C#
203 lines
7.0 KiB
C#
using System.Text;
|
|
using EmbedIO;
|
|
using EmbedIO.Routing;
|
|
using EmbedIO.WebApi;
|
|
using Kyubey.Database;
|
|
using Kyubey.Interop;
|
|
|
|
namespace Kyubey;
|
|
|
|
public class ServiceController : WebApiController
|
|
{
|
|
[Route(HttpVerbs.Get, "/GameEntry")]
|
|
public async Task GameEntry()
|
|
{
|
|
var maybeUsername = Request.QueryString.Get("id");
|
|
var maybePassword = Request.QueryString.Get("pass");
|
|
var maybeVersion = Request.QueryString.Get("ver");
|
|
|
|
if (maybeUsername is not { } username ||
|
|
maybePassword is not { } password ||
|
|
maybeVersion is not "1.32")
|
|
{
|
|
throw HttpException.BadRequest();
|
|
}
|
|
|
|
var hashedPass = Utils.ComputeHash(password);
|
|
|
|
var loginUser = JewelDbContext.Users.FindOne(e => e.Username == username && e.Password == hashedPass);
|
|
var response = loginUser is not null ? "0" : "1";
|
|
var buf = Encoding.ASCII.GetBytes(response);
|
|
|
|
Response.ContentType = "text/plain";
|
|
Response.ContentEncoding = Encoding.ASCII;
|
|
Response.ContentLength64 = buf.Length;
|
|
|
|
await Response.OutputStream.WriteAsync(buf, 0, buf.Length);
|
|
}
|
|
|
|
[Route(HttpVerbs.Get, "/GetName")]
|
|
public async Task GetName()
|
|
{
|
|
var maybeId = Request.QueryString.Get("id");
|
|
if (maybeId is not { } id)
|
|
{
|
|
throw HttpException.BadRequest();
|
|
}
|
|
|
|
var rankingUser = JewelDbContext.Users.FindOne(e => e.Username == id);
|
|
if (rankingUser is null) throw HttpException.NotFound("No such userid");
|
|
|
|
var response = rankingUser.RankingName;
|
|
var buf = Encoding.ASCII.GetBytes(response);
|
|
|
|
Response.ContentType = "text/plain";
|
|
Response.ContentEncoding = Encoding.ASCII;
|
|
Response.ContentLength64 = buf.Length;
|
|
|
|
await Response.OutputStream.WriteAsync(buf, 0, buf.Length);
|
|
}
|
|
|
|
[Route(HttpVerbs.Get, "/GetMessage")]
|
|
public async Task GetMessage()
|
|
{
|
|
var responses = new[]
|
|
{
|
|
"jewelry master lives, but why",
|
|
"did you know this game sends your password in cleartext? it's hashed server-side though!",
|
|
"this is not an entirely serious project",
|
|
"powered by IDA - The Interactive Disassembler",
|
|
$"powered by Microsoft .NET version {Environment.Version}",
|
|
"powered by anime music",
|
|
"greetz 2 mihara, your EULA can't stop me",
|
|
"did you know i can make this text say anything i want",
|
|
"i wonder how many of these scrolling messages there are"
|
|
};
|
|
|
|
var responseIdx = Random.Shared.Next(responses.Length);
|
|
var response = $"the server says: {responses[responseIdx]}";
|
|
var buf = Encoding.ASCII.GetBytes(response);
|
|
|
|
Response.ContentType = "text/plain";
|
|
Response.ContentEncoding = Encoding.ASCII;
|
|
Response.ContentLength64 = buf.Length;
|
|
|
|
await Response.OutputStream.WriteAsync(buf, 0, buf.Length);
|
|
}
|
|
|
|
[Route(HttpVerbs.Get, "/GetRanking")]
|
|
public async Task GetRanking()
|
|
{
|
|
// view = -1 means top 10, 0 and above mean pages in the global ranking
|
|
var view = int.Parse(Request.QueryString.Get("view")!);
|
|
var mode = (JewelryMode)int.Parse(Request.QueryString.Get("mode")!);
|
|
var userId = Request.QueryString.Get("id");
|
|
|
|
var response = "";
|
|
|
|
if (userId is not null && view == -1 || userId is null) // ?????? this game makes no sense dude
|
|
{
|
|
var factor = view == -1 ? 0 : view;
|
|
if (factor > 0 && JewelDbContext.Scores.Count() < 11)
|
|
{
|
|
response = "";
|
|
}
|
|
else
|
|
{
|
|
var globalRanking = JewelDbContext.Scores
|
|
.Find(e => e.GameMode == mode)
|
|
.OrderByDescending(e => e.Points)
|
|
.Skip(factor*view)
|
|
.Take(10)
|
|
.ToList();
|
|
|
|
if (globalRanking.Any())
|
|
{
|
|
response = $"{factor}\n";
|
|
}
|
|
|
|
foreach (var score in globalRanking) response += score.ToString();
|
|
}
|
|
} else // personal ranking
|
|
{
|
|
var personalRanking = JewelDbContext.Scores
|
|
.Find(e => e.User.Username == userId && e.GameMode == mode)
|
|
.OrderByDescending(e => e.Points)
|
|
.Take(10)
|
|
.ToList();
|
|
|
|
if (personalRanking.Any())
|
|
{
|
|
response = "0\n";
|
|
}
|
|
|
|
foreach (var score in personalRanking) response += score.ToString();
|
|
}
|
|
|
|
var buf = Encoding.ASCII.GetBytes(response);
|
|
Response.ContentType = "text/plain";
|
|
Response.ContentEncoding = Encoding.ASCII;
|
|
Response.ContentLength64 = buf.Length;
|
|
await Response.OutputStream.WriteAsync(buf, 0, buf.Length);
|
|
}
|
|
|
|
[Route(HttpVerbs.Post, "/ScoreEntry")]
|
|
public async Task ScoreEntry()
|
|
{
|
|
var id = Request.QueryString.Get("id")!;
|
|
var mode = (JewelryMode)int.Parse(Request.QueryString.Get("mode")!);
|
|
var score = uint.Parse(Request.QueryString.Get("score")!);
|
|
var jewel = uint.Parse(Request.QueryString.Get("jewel")!);
|
|
var rank = int.Parse(Request.QueryString.Get("class")!); // probably title
|
|
var time = uint.Parse(Request.QueryString.Get("time")!);
|
|
var level = uint.Parse(Request.QueryString.Get("level")!);
|
|
|
|
var maybeUser = JewelDbContext.Users.FindOne(e => e.Username == id);
|
|
if (maybeUser is not {} user)
|
|
{
|
|
throw HttpException.NotFound("No such userid");
|
|
}
|
|
|
|
// TODO: add compression to replay data
|
|
var rawReplay = await HttpContext.GetRequestBodyAsByteArrayAsync();
|
|
var replay = Convert.ToBase64String(rawReplay);
|
|
|
|
var scoreRecord = new Score()
|
|
{
|
|
Id = Utils.GenerateCheapGuid(),
|
|
User = user,
|
|
GameMode = mode,
|
|
Points = score,
|
|
Class = rank,
|
|
Time = time,
|
|
Jewels = jewel,
|
|
Level = level,
|
|
Replay = replay,
|
|
Timestamp = DateTime.Now
|
|
};
|
|
|
|
JewelDbContext.Scores.Insert(scoreRecord);
|
|
JewelDbContext.Scores.EnsureIndex(e => e.Points);
|
|
|
|
Response.ContentType = "text/plain";
|
|
Response.ContentEncoding = Encoding.ASCII;
|
|
}
|
|
|
|
[Route(HttpVerbs.Get, "/GetReplay")]
|
|
public async Task GetReplay()
|
|
{
|
|
Response.ContentType = "application/octet-stream";
|
|
|
|
var replayId = Request.QueryString.Get("id")!;
|
|
var score = JewelDbContext.Scores.FindOne(e => e.Id == replayId);
|
|
if (score is null)
|
|
{
|
|
throw HttpException.NotFound("No such replay");
|
|
}
|
|
|
|
// deconvert the replay
|
|
var replayBytes = Convert.FromBase64String(score.Replay);
|
|
// fire it down the byte hole
|
|
await Response.OutputStream.WriteAsync(replayBytes, 0, replayBytes.Length);
|
|
}
|
|
} |