Luski.Net/Luski.net/MainServer.cs

278 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.Json.Serialization.Metadata;
using System.Threading;
using System.Threading.Tasks;
using JacobTechEncryption;
using Luski.net.Enums.Main;
using Luski.net.Interfaces;
using Luski.net.JsonTypes;
using Luski.net.JsonTypes.HTTP;
using Luski.net.Structures.Main;
using Luski.Shared.PublicServers.V1.ClientToServer.HTTP;
using Luski.Shared.PublicServers.V1.Enums;
using Luski.Shared.PublicServers.V1.ServerToClient.HTTP;
using ChannelType = Luski.net.Enums.Main.ChannelType;
namespace Luski.net;
public partial class MainServer : Server
{
internal MainServer(string Domain, string API_Version):
base(Domain, API_Version)
{
}
public MainSocketAppUser User { get; internal set; } = default!;
public List<MainSocketChannel> chans { get; } = new();
public async Task<MainSocketRemoteUser> SendFriendResult(long user, bool answer, CancellationToken CancellationToken)
{
FriendRequestResult json = await SendServer("FriendRequestResult",
new FriendRequestResultOut()
{
Id = user,
Result = answer
},
FriendRequestResultOutContext.Default.FriendRequestResultOut,
FriendRequestResultContext.Default.FriendRequestResult,
CancellationToken);
if (json is not null && json.Error is null && json.ErrorMessage is null && answer && json.Channel is not null)
{
MainSocketDMChannel chan = await GetChannel((long)json.Channel, MainSocketDMChannelContext.Default.MainSocketDMChannel, CancellationToken);
_ = chan.StartKeyProcessAsync(CancellationToken);
chans.Add(chan);
}
else
{
throw new Exception(json?.Error.ToString());
}
return GetUser(user, MainSocketRemoteUserContext.Default.MainSocketRemoteUser, CancellationToken).Result;
}
public async Task<MainSocketRemoteUser> SendFriendRequest(long code, CancellationToken CancellationToken)
{
string ccode = Convert.ToBase64String(Encryption.Hashing.SHA256(Encoding.Unicode.GetBytes(code.ToString())));
FriendRequestResult? json = await SendServer("FriendRequest", new FriendRequest() { code = ccode}, FriendRequestContext.Default.FriendRequest, FriendRequestResultContext.Default.FriendRequestResult, CancellationToken);
if (json.StatusCode != HttpStatusCode.Accepted)
{
if (json is not null && json.Error is not null)
{
switch ((ErrorCode)(int)json.Error)
{
case ErrorCode.InvalidToken:
throw new Exception("Your current token is no longer valid");
case ErrorCode.ServerError:
throw new Exception($"Error from server: {json.ErrorMessage}");
case ErrorCode.InvalidPostData:
throw new Exception("The post data dent to the server is not the correct format. This may be because you app is couropt or you are using the wron API version");
case ErrorCode.Forbidden:
throw new Exception("You already have an outgoing request or the persone is not real");
}
}
if (json is not null && json.Channel is not null)
{
MainSocketDMChannel chan = await GetChannel((long)json.Channel, MainSocketDMChannelContext.Default.MainSocketDMChannel, CancellationToken);
_ = chan.StartKeyProcessAsync(CancellationToken);
chans.Add(chan);
}
}
MainSocketRemoteUser b = await GetUser(code, MainSocketRemoteUserContext.Default.MainSocketRemoteUser, CancellationToken);
if (json.Channel is not null)
b.FriendStatus = FriendStatus.Friends;
else
b.FriendStatus = FriendStatus.PendingOut;
return b;
}
public async Task<TChannel> GetChannel<TChannel>(long Channel, CancellationToken CancellationToken) where TChannel : MainSocketChannel, new()
{
TChannel Return = new();
switch (Return)
{
case MainSocketDMChannel:
Return = (await GetChannel(Channel, MainSocketDMChannelContext.Default.MainSocketDMChannel, CancellationToken) as TChannel)!;
break;
case MainSocketGroupChannel:
Return = (await GetChannel(Channel, MainSocketGroupChannelContext.Default.MainSocketGroupChannel, CancellationToken) as TChannel)!;
break;
case MainSocketTextChannel:
Return = (await GetChannel(Channel, MainSocketTextChannelContext.Default.MainSocketTextChannel, CancellationToken) as TChannel)!;
break;
case MainSocketChannel:
Return = (await GetChannel(Channel, MainSocketChannelContext.Default.MainSocketChannel, CancellationToken) as TChannel)!;
break;
case null:
throw new NullReferenceException(nameof(TChannel));
default:
throw new Exception("Unknown channel type");
}
return Return;
}
internal async Task<TChannel> GetChannel<TChannel>(long id, JsonTypeInfo<TChannel> Json, CancellationToken CancellationToken) where TChannel : MainSocketChannel, new()
{
TChannel request;
if (chans.Count > 0 && chans.Any(s => s.Id == id))
{
return (chans.Where(s => s is TChannel && s.Id == id).First() as TChannel)!;
}
while (true)
{
if (CanRequest)
{
request = await GetFromServer($"SocketChannel/Get/{id}", Json, CancellationToken);
break;
}
}
if (request is null) throw new Exception("Something was wrong with the server responce");
if (request.Error is null)
{
if (chans.Count > 0 && chans.Any(s => s.Id == request.Id))
{
foreach (MainSocketChannel? p in chans.Where(s => s.Id == request.Id))
{
chans.Remove(p);
}
}
request.Server = this;
chans.Add(request);
return request;
}
throw request.Error switch
{
ErrorCode.InvalidToken => new Exception("Your current token is no longer valid"),
ErrorCode.Forbidden => new Exception("The server rejected your request"),
ErrorCode.ServerError => new Exception("Error from server: " + request.ErrorMessage),
ErrorCode.InvalidURL or ErrorCode.MissingHeader => new Exception(request.ErrorMessage),
_ => new Exception($"Unknown data: '{request.ErrorMessage}'"),
};
}
public Task<Tuser> GetUser<Tuser>(long UserID, CancellationToken CancellationToken) where Tuser : MainSocketUserBase, new()
{
Tuser user = new();
switch (user)
{
case MainSocketAppUser:
user = (GetUser(UserID, MainSocketAppUserContext.Default.MainSocketAppUser, CancellationToken).Result as Tuser)!;
break;
case MainSocketRemoteUser:
user = (GetUser(UserID, MainSocketRemoteUserContext.Default.MainSocketRemoteUser, CancellationToken).Result as Tuser)!;
break;
case MainSocketUserBase:
user = (GetUser(UserID, MainSocketUserBaseContext.Default.MainSocketUserBase, CancellationToken).Result as Tuser)!;
break;
case null:
throw new NullReferenceException(nameof(Tuser));
default:
throw new Exception("Unknown channel type");
}
return Task.FromResult(user);
}
public async Task<MainSocketMessage> GetMessage(long id, CancellationToken CancellationToken)
{
MainSocketMessage message;
while (true)
{
if (CanRequest)
{
message = await GetFromServer("socketmessage",
MainSocketMessageContext.Default.MainSocketMessage,
CancellationToken,
new KeyValuePair<string, string?>("msg_id", id.ToString()));
break;
}
}
if (message is not null)
{
message.Server = this;
return message;
}
throw new Exception("Server did not return a message");
}
/// <summary>
/// Sends the server a request to update the <paramref name="Status"/> of you account
/// </summary>
/// <param name="Status">The <see cref="UserStatus"/> you want to set your status to</param>
/// <exception cref="Exception"></exception>
public async Task<Task> UpdateStatus(UserStatus Status, CancellationToken CancellationToken)
{
STC? data = await SendServer("SocketUserProfile/Status", new StatusUpdateCTS() { Status = Status }, StatusUpdateCTSContext.Default.StatusUpdateCTS, STCContext.Default.STC, CancellationToken);
if (data.Error is not null && ((int)data.StatusCode < 200 || (int)data.StatusCode > 299))
{
if (data?.ErrorMessage is not null) throw new Exception(data.ErrorMessage);
if (data?.Error is not null) throw new Exception(((int)data.Error).ToString());
else throw new Exception("Something went worng");
}
User.Status = Status;
return Task.CompletedTask;
}
internal async Task<Tuser> GetUser<Tuser>(long UserId, JsonTypeInfo<Tuser> Json, CancellationToken CancellationToken) where Tuser : MainSocketUserBase, new()
{
Tuser user;
if (poeople.Count > 0 && poeople.Any(s => s.Id == UserId))
{
Tuser temp = poeople.Where(s => s is Tuser && s.Id == UserId).Cast<Tuser>().FirstOrDefault()!;
if (temp is MainSocketRemoteUser && (temp as MainSocketRemoteUser)!.Channel == null)
{
foreach (MainSocketDMChannel chan in chans.Where(s => s is MainSocketDMChannel).Cast<MainSocketDMChannel>())
{
if (chan.Type == ChannelType.DM && chan.Id != 0 && chan.MemberIdList is not null)
{
if (chan.MemberIdList.Any(s => s == UserId)) (temp as MainSocketRemoteUser)!.Channel = chan;
}
}
}
return temp;
}
while (true)
{
if (CanRequest)
{
user = await GetFromServer("socketuser",
Json,
CancellationToken,
new KeyValuePair<string, string?>("id", UserId.ToString()));
break;
}
}
if (user is null) throw new Exception("Server did not return a user");
if (poeople.Count > 0 && poeople.Any(s => s.Id == UserId))
{
foreach (IUser? p in poeople.Where(s => s.Id == UserId))
{
poeople.Remove(p);
}
}
user.Server = this;
if (user is MainSocketRemoteUser && (user as MainSocketRemoteUser)!.Channel == null)
{
foreach (MainSocketDMChannel chan in chans.Where(s => s is MainSocketDMChannel).Cast<MainSocketDMChannel>())
{
if (chan.Type == ChannelType.DM && chan.Id != 0 && chan.MemberIdList is not null)
{
if (chan.MemberIdList.Any(s => s == UserId)) (user as MainSocketRemoteUser)!.Channel = chan;
}
}
}
poeople.Add(user);
return user;
}
}