add base on map registration

This commit is contained in:
Дмитрий Шиманский
2023-11-16 19:08:16 +03:00
parent f9cd50d646
commit b8db704fef
14 changed files with 661 additions and 37 deletions

View File

@@ -1,34 +1,42 @@
using Discord;
using DiscordApp.Database;
using Microsoft.AspNetCore.Mvc;
using System.Text.Json.Nodes;
namespace DiscordApp.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
public class redirects : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
[HttpGet("/redirects/{uri}")]
public IActionResult Get(string uri)
{
_logger = logger;
var data = Startup.appDbContext.Redirects.First(k => k.Id == uri);
Startup.appDbContext.Redirects.Remove(data);
Startup.appDbContext.SaveChanges();
return Redirect(data.url);
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
[HttpPost("addOnMap")]
public ActionResult Create(string bodyContent)
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
JsonNode jsonBodyContent = JsonNode.Parse(bodyContent);
string[] paymentData = jsonBodyContent["data"].ToString().Split(";");
var channelId = paymentData[1].Split(":")[1];
var channel = Startup.discordSocketClient.GetChannel(ulong.Parse(channelId)) as ITextChannel;
var message = channel.GetMessagesAsync().LastAsync().Result.Last() as IUserMessage;
message.ModifyAsync(func =>
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
func.Content = "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!";
func.Components = new ComponentBuilder()
.WithButton("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "addBaseOnMapModalSender")
.Build();
}).RunSynchronously();
return Ok();
}
}
}

View File

@@ -15,7 +15,7 @@ namespace DiscordApp.Database
public DbSet<Bizness> Bizness { get; set; }
public DbSet<Reports> Reports { get; set; }
public DbSet<Certificate> Certificates { get; set; }
public DbSet<Redirects> Redirects { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);

View File

@@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
namespace DiscordApp.Database.Tables
{
[Table("Redirects", Schema = "public")]
public class Redirects
{
[Key]
public string Id { get; set; }
public string url { get; set; }
}
}

View File

@@ -0,0 +1,26 @@
using Discord.Interactions;
using Discord;
namespace DiscordApp.Justice.Commands
{
public class Cities : InteractionModuleBase<SocketInteractionContext>
{
[SlashCommand("cities-embed", "Отправляет сообщение с кнопками для регистрации")]
[DefaultMemberPermissions(GuildPermission.Administrator)]
public async Task sendCityEmbed()
{
await DeferAsync(true);
var Embed = new EmbedBuilder()
.WithTitle("**Регистрация базы на карту!**")
.WithDescription("Ниже вы можете нажать на кнопку для подачи заявки на добавления базы на карту!")
.WithColor(Color.Blue)
.Build();
var Components = new ComponentBuilder()
.WithButton(new ButtonBuilder() { CustomId = "addBaseOnMap", Label = "Добавить", Style = ButtonStyle.Success})
.Build();
await Context.Channel.SendMessageAsync(embed: Embed, components: Components);
await FollowupAsync("OK!");//, ephemeral: true);
}
}
}

View File

@@ -0,0 +1,129 @@
using Discord;
using Discord.Interactions;
using DiscordApp.Database.Tables;
using DiscordApp.Justice.Modals;
using DiscordApp.Types;
namespace DiscordApp.Justice.Interactions
{
public class CitiesInteractions : InteractionModuleBase<SocketInteractionContext>
{
[ComponentInteraction("addBaseOnMap")]
public async Task addBaseInteraction()
{
await DeferAsync(true);
var paymentData = new spworlds.Types.PaymentData()
{
Amount = 16,
Data = $"user:{Context.User.Id};channel:{Context.Channel.Id};",
RedirectUrl = Context.Interaction.GetOriginalResponseAsync().Result.GetJumpUrl(),
WebHookUrl = "https://api.yawaflua.ru/addOnMap/"
};
var uri = await Startup.sp.InitPayment(paymentData);
var redirectUri = Guid.NewGuid().ToString();
var redirectTable = new Redirects() { Id = redirectUri , url = uri};
Startup.appDbContext.Redirects.Add(redirectTable);
Startup.appDbContext.SaveChanges();
await FollowupAsync("Нажмите на кнопку ниже для оплаты", components: new ComponentBuilder().WithButton("Оплатить", url: $"https://api.yawaflua.ru/redirects/{redirectUri}", style: ButtonStyle.Link).Build());//, ephemeral: true);
}
[ComponentInteraction("addBaseOnMapModalSender")]
public async Task sendModal() => await RespondWithModalAsync<ICitiesModal>("newBaseOnMapModal");
[ModalInteraction("newBaseOnMapModal")]
public async Task addBaseOnMapModal(ICitiesModal modal)
{
await DeferAsync(true);
var defaultSpUser = await Startup.sp.GetUser(Context.User.Id.ToString());
var fields = new List<EmbedFieldBuilder>()
{
new EmbedFieldBuilder()
.WithName("Название")
.WithValue(modal.Name),
new EmbedFieldBuilder()
.WithName("Описание")
.WithValue($"{modal.description}"),
new EmbedFieldBuilder()
.WithName("X Координата")
.WithValue(modal.xCoordinate),
new EmbedFieldBuilder()
.WithName("Y Координата")
.WithValue(modal.yCoordinate),
};
var footer = new EmbedFooterBuilder()
.WithText(Context.User.Id.ToString())
.WithIconUrl(((IGuildUser)Context.User).GetDisplayAvatarUrl());
var components = new ComponentBuilder()
.WithButton(customId: "accessNewBase", label: "✅")
.WithButton(customId: "declineNewBase", label: "❌")
.Build();
var embed = new EmbedBuilder()
.WithTitle("Заявка на регистрацию базы")
.WithThumbnailUrl(defaultSpUser.GetSkinPart(spworlds.Types.SkinPart.face))
.WithFooter(footer)
.WithFields(fields)
.Build();
var channel = Context.Guild.GetTextChannel(1174722397820174439);
await channel.SendMessageAsync("@ #here", embed: embed, components: components);
await FollowupAsync("Заявка подана и передана ответственным лицам. Ожидайте!", ephemeral: true);
}
[ComponentInteraction("accessNewBase")]
public async Task addBaseOnMap()
{
await DeferAsync(true);
var embed = Context.Interaction.GetOriginalResponseAsync().Result.Embeds.First();
var embedFields = embed.Fields;
var startup = new Startup();
var defaultSpUser = await Startup.sp.GetUser(embed.Footer.Value.Text);
var spUser = await startup.getUserData(defaultSpUser.Name);
int xCoordinate;
int zCoordinate;
if(spUser.city != null)
{
await FollowupAsync("Игрок уже состоит в каком-то городе!");
return;
}
if (!int.TryParse(embedFields[2].Value, out xCoordinate) || !int.TryParse(embedFields[3].Value, out zCoordinate))
{
await FollowupAsync("Ошибка, координаты неправильные!");
return;
}
var city = new SPCity()
{
description = embedFields[1].Value,
name = embedFields[0].Value,
mayor = spUser.id,
x = xCoordinate,
z = zCoordinate,
};
var components = new ComponentBuilder()
.WithButton(customId: "accessNewBase", label: "✅", disabled: true)
.WithButton(customId: "declineNewBase", label: "❌", disabled: true)
.Build();
await ModifyOriginalResponseAsync(func => { func.Components = components; func.Content = $"Заявку принял {Context.User.Mention}"; });
try
{
await startup.addSityOnMap(city);
await FollowupAsync("Все готово!");
}
catch
{
await FollowupAsync("Какая-то ошибка, чекни логи");
}
}
}
}

View File

@@ -155,7 +155,7 @@ namespace DiscordApp.Justice.Interactions
Supporter supporter;
Random random = new();
spworlds.Types.User spUser = await spworlds.Types.User.CreateUser(name);
Root spUserData = await startup.getUserData(name);
var spUserData = await startup.getUserData(name);
DateTimeOffset toTime;
DateOnly birthDate;
int id;
@@ -304,7 +304,7 @@ namespace DiscordApp.Justice.Interactions
Supporter supporter;
Random random = new();
spworlds.Types.User spUser = await spworlds.Types.User.CreateUser(name);
Root spUserData = await startup.getUserData(name);
var spUserData = await startup.getUserData(name);
DateTimeOffset toTime;
DateOnly birthDate;
int id = random.Next(00001, 99999);

View File

@@ -0,0 +1,27 @@
using Discord;
using Discord.Interactions;
namespace DiscordApp.Justice.Modals
{
public class ICitiesModal : IModal
{
public string Title => "Регистрация базы";
[InputLabel("Название на карте")]
[ModalTextInput("Name", TextInputStyle.Short, placeholder: "Сигмасити", maxLength: 100)]
public string Name { get; set; }
[InputLabel("Описание на карте")]
[ModalTextInput("BaseDescription", TextInputStyle.Paragraph, placeholder: "Меня зовут Кира Йошикаге...")]
public string description { get; set; }
[InputLabel("Х координата")]
[ModalTextInput("xCoordinate", TextInputStyle.Short, placeholder: "70", maxLength: 4)]
public int xCoordinate { get; set; }
[InputLabel("Y координата")]
[ModalTextInput("yCoordinate", TextInputStyle.Short, placeholder: "90", maxLength: 4)]
public int yCoordinate { get; set; }
}
}

View File

@@ -51,7 +51,8 @@ namespace DiscordApp
{
var request = await http.GetAsync("https://api.mcsrvstat.us/3/pl.spworlds.ru");
JsonNode responseAboutPL = JsonNode.Parse(request.Content.ReadAsStringAsync().Result);
if (responseAboutPL["online"].Equals("false")) await client.SetGameAsync($"выключенный PL", "https://yaflay.ru/", ActivityType.Watching);
bool result;
if (bool.TryParse(responseAboutPL["online"].ToString(), out result) || result) await client.SetGameAsync($"выключенный PL", "https://yaflay.ru/", ActivityType.Watching);
else await client.SetGameAsync($"онлайн на PL: {responseAboutPL["players"]["online"]}", "https://yaflay.ru/", ActivityType.Watching);
}
finally

View File

@@ -0,0 +1,316 @@
// <auto-generated />
using System;
using DiscordApp.Database;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace DiscordApp.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20231116154850_Migrate16111848")]
partial class Migrate16111848
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.13")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("DiscordApp.Database.Tables.ArtsPatents", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<long>("Date")
.HasColumnType("bigint");
b.Property<string>("Employee")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<int[]>("Number")
.IsRequired()
.HasColumnType("integer[]");
b.Property<string>("Size")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("isAllowedToResell")
.HasColumnType("boolean");
b.Property<int>("passportId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("passportId");
b.ToTable("ArtsPatent", "public");
});
modelBuilder.Entity("DiscordApp.Database.Tables.Autobranches", b =>
{
b.Property<decimal>("ChannelId")
.ValueGeneratedOnAdd()
.HasColumnType("numeric(20,0)");
b.Property<string>("BranchName")
.IsRequired()
.HasColumnType("text");
b.HasKey("ChannelId");
b.ToTable("Autobranches", "public");
});
modelBuilder.Entity("DiscordApp.Database.Tables.Bizness", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("ApplicantId")
.HasColumnType("integer");
b.Property<int[]>("BiznessEmployes")
.IsRequired()
.HasColumnType("integer[]");
b.Property<string>("BiznessName")
.IsRequired()
.HasColumnType("text");
b.Property<string>("BiznessType")
.IsRequired()
.HasColumnType("text");
b.Property<int>("CardNumber")
.HasColumnType("integer");
b.Property<long>("Date")
.HasColumnType("bigint");
b.Property<string>("Employee")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ApplicantId");
b.ToTable("Bizness", "public");
});
modelBuilder.Entity("DiscordApp.Database.Tables.BooksPatents", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Annotation")
.IsRequired()
.HasColumnType("text");
b.Property<long>("Date")
.HasColumnType("bigint");
b.Property<string>("Employee")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Janre")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("isAllowedToResell")
.HasColumnType("boolean");
b.Property<int>("passportId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("passportId");
b.ToTable("BooksPatent", "public");
});
modelBuilder.Entity("DiscordApp.Database.Tables.Certificate", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<DateOnly>("Date")
.HasColumnType("date");
b.Property<int>("DocumentId")
.HasColumnType("integer");
b.Property<string>("DocumentType")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Employee")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Text")
.IsRequired()
.HasColumnType("text");
b.Property<int>("passportId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("passportId");
b.ToTable("Certificate", "public");
});
modelBuilder.Entity("DiscordApp.Database.Tables.Passport", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Applicant")
.IsRequired()
.HasColumnType("text");
b.Property<long>("Date")
.HasColumnType("bigint");
b.Property<decimal>("Employee")
.HasColumnType("numeric(20,0)");
b.Property<string>("Gender")
.IsRequired()
.HasColumnType("text");
b.Property<string>("RpName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("Support")
.HasColumnType("integer");
b.Property<long>("birthDate")
.HasColumnType("bigint");
b.HasKey("Id");
b.ToTable("Passport", "public");
});
modelBuilder.Entity("DiscordApp.Database.Tables.Redirects", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("url")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Redirects", "public");
});
modelBuilder.Entity("DiscordApp.Database.Tables.Reports", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Employee")
.IsRequired()
.HasColumnType("text");
b.Property<int>("type")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("Reports", "public");
});
modelBuilder.Entity("DiscordApp.Database.Tables.ArtsPatents", b =>
{
b.HasOne("DiscordApp.Database.Tables.Passport", "passport")
.WithMany()
.HasForeignKey("passportId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("passport");
});
modelBuilder.Entity("DiscordApp.Database.Tables.Bizness", b =>
{
b.HasOne("DiscordApp.Database.Tables.Passport", "Applicant")
.WithMany()
.HasForeignKey("ApplicantId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Applicant");
});
modelBuilder.Entity("DiscordApp.Database.Tables.BooksPatents", b =>
{
b.HasOne("DiscordApp.Database.Tables.Passport", "passport")
.WithMany()
.HasForeignKey("passportId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("passport");
});
modelBuilder.Entity("DiscordApp.Database.Tables.Certificate", b =>
{
b.HasOne("DiscordApp.Database.Tables.Passport", "passport")
.WithMany()
.HasForeignKey("passportId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("passport");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,35 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace DiscordApp.Migrations
{
/// <inheritdoc />
public partial class Migrate16111848 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Redirects",
schema: "public",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
url = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Redirects", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Redirects",
schema: "public");
}
}
}

View File

@@ -230,6 +230,20 @@ namespace DiscordApp.Migrations
b.ToTable("Passport", "public");
});
modelBuilder.Entity("DiscordApp.Database.Tables.Redirects", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("url")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Redirects", "public");
});
modelBuilder.Entity("DiscordApp.Database.Tables.Reports", b =>
{
b.Property<int>("Id")

View File

@@ -10,6 +10,7 @@ using DiscordApp.Types;
using DotNetEd.CoreAdmin;
using DotNetEd.CoreAdmin.Controllers;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Primitives;
@@ -28,6 +29,7 @@ namespace DiscordApp
public static AppDbContext appDbContext;
public static SPWorlds sp;
private readonly HttpClient client;
public static DiscordSocketClient discordSocketClient;
private readonly DiscordSocketConfig socketConfig = new()
{
GatewayIntents = GatewayIntents.All,
@@ -106,13 +108,61 @@ namespace DiscordApp
var responseMessage = client.PostAsync("auth/refresh_token", content).Result;
Console.WriteLine(responseMessage.Content.ReadAsStringAsync().Result.ToString());
}
public async Task<Root> getUserData(string userName)
public async Task<SPUser> getUserData(string userName)
{
var request = await client.GetAsync($"pl/accounts/{userName}");
await Console.Out.WriteLineAsync(request.Content.ToString());
Root response = JsonConvert.DeserializeObject<Root>(request.Content.ReadAsStringAsync().Result.ToString());
await Console.Out.WriteLineAsync(request.Content.ReadAsStringAsync().Result);
SPUser response = JsonConvert.DeserializeObject<SPUser>(request.Content.ReadAsStringAsync().Result.ToString());
return response;
}
public async Task<IEnumerable<SPCity>> getAllSities()
{
var citiesArray = new List<SPCity>();
var request = await client.GetAsync("https://spworlds.ru/api/pl/cities");
JsonNode jsonBody = await request.Content.ReadFromJsonAsync<JsonNode>();
foreach (JsonNode node in jsonBody.AsArray())
{
citiesArray.Add(JsonConvert.DeserializeObject<SPCity>(node.ToJsonString()));
}
return citiesArray;
}
public async Task<SPCity?> addSityOnMap(SPCity city)
{
try
{
var request = await client.PostAsync("https://spworlds.ru/api/pl/cities", JsonContent.Create(city));
if (request.StatusCode.HasFlag(HttpStatusCode.OK))
{
return city;
}
else
{
throw new Exception("Unknown error from site!");
}
}
catch (Exception ex)
{
await Console.Out.WriteLineAsync(ex.Message);
return null;
}
}
public async Task<SPCity> deleteSityFromMap(SPCity city)
{
var request = await client.DeleteAsync($"https://spworlds.ru/api/pl/cities/{city.id}");
if (request.StatusCode.Equals(200))
{
return city;
}
else
{
throw new Exception("Unknown error from site!");
}
}
public void ConfigureServices(IServiceCollection services)
{
@@ -132,16 +182,12 @@ namespace DiscordApp
.AddSingleton<JusticeHandler>()
.AddSingleton(sp)
.AddDbContext<AppDbContext>(c => c.UseNpgsql(@"Host=185.104.112.180;Username=yaflay;Password=hQgtruasSS;Database=poopland"))
.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "Bearer";
options.DefaultChallengeScheme = "Bearer";
}).AddScheme<AuthenticationSchemeOptions, AuthanticationByBearerToken>("Bearer", options => { });
;
serviceProvider = services.BuildServiceProvider();
appDbContext = serviceProvider.GetRequiredService<AppDbContext>();
discordSocketClient = serviceProvider.GetRequiredService<DiscordSocketClient>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
@@ -155,13 +201,9 @@ namespace DiscordApp
c.RouteTemplate = "/swagger/v1/swagger.json";
});
}
app.UseCoreAdminCustomAuth(k => Task.FromResult(true));
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseCoreAdminCustomUrl("admin/private/panel");
app.UseAuthentication();
app.UseAuthorization();
app.UseCors(k => { k.AllowAnyHeader(); k.AllowAnyMethod(); k.AllowAnyOrigin(); });
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();

12
Types/SPCity.cs Normal file
View File

@@ -0,0 +1,12 @@
namespace DiscordApp.Types
{
public class SPCity
{
public string? mayor { get; set; }
public string? description { get; set; }
public string? id { get; set; }
public string name { get; set; }
public int x { get; set; }
public int z { get; set; }
}
}

View File

@@ -21,7 +21,7 @@
public string id { get; set; }
}
public class Root
public class SPUser
{
public string id { get; set; }
public bool isBanned { get; set; }