2023-01-01 22:50:39 -05:00
using System ;
using System.Collections.Generic ;
using System.IO ;
2023-07-03 23:24:35 -04:00
using System.Linq ;
2023-01-01 22:50:39 -05:00
using System.Net.Http ;
using System.Net.Http.Json ;
using System.Text.Json ;
using System.Text.Json.Serialization.Metadata ;
2023-07-03 23:24:35 -04:00
using System.Threading ;
2023-01-01 22:50:39 -05:00
using System.Threading.Tasks ;
2023-07-03 23:24:35 -04:00
using Luski.net.Enums ;
using Luski.net.Interfaces ;
using Luski.net.JsonTypes ;
using Luski.net.JsonTypes.BaseTypes ;
using Luski.net.JsonTypes.HTTP ;
using Luski.net.Structures ;
using Luski.net.Structures.Main ;
using Luski.net.Structures.Public ;
using File = System . IO . File ;
2023-01-01 22:50:39 -05:00
namespace Luski.net ;
2023-07-03 23:24:35 -04:00
public partial class Server < TUser > : IServer
2023-01-01 22:50:39 -05:00
{
2023-07-03 23:24:35 -04:00
internal Server ( )
{ }
public async Task < byte [ ] > GetAvatar ( CancellationToken CancellationToken )
2023-01-01 22:50:39 -05:00
{
2023-07-03 23:24:35 -04:00
if ( Cache ! = null )
{
bool isc = File . Exists ( $"{Cache}/servers/{Domain}" ) ;
if ( ! isc ) await GetFromServer ( $"socketserver/Avatar/" , $"{Cache}/servers/{Domain}-{ApiVersion}" , CancellationToken ) ;
}
return File . ReadAllBytes ( $"{Cache}/servers/{Domain}" ) ;
2023-01-01 22:50:39 -05:00
}
2023-07-03 23:24:35 -04:00
public async Task < Tuser > GetUser < Tuser > ( long UserID , CancellationToken CancellationToken ) where Tuser : SocketUserBase , new ( )
2023-01-01 22:50:39 -05:00
{
2023-07-03 23:24:35 -04:00
Tuser user = new ( ) ;
switch ( user )
2023-01-01 22:50:39 -05:00
{
2023-07-03 23:24:35 -04:00
case MainSocketAppUser :
user = ( GetUser ( UserID , MainSocketAppUserContext . Default . MainSocketAppUser , CancellationToken ) . Result as Tuser ) ! ;
break ;
case PublicSocketAppUser :
user = ( GetUser ( UserID , PublicSocketAppUserContext . Default . PublicSocketAppUser , CancellationToken ) . Result as Tuser ) ! ;
break ;
case SocketUserBase :
user = ( GetUser ( UserID , SocketUserBaseContext . Default . SocketUserBase , CancellationToken ) . Result as Tuser ) ! ;
break ;
case null :
throw new NullReferenceException ( nameof ( Tuser ) ) ;
default :
throw new Exception ( "Unknown channel type" ) ;
2023-01-01 22:50:39 -05:00
}
2023-07-03 23:24:35 -04:00
return user ;
}
public async Task < TChannel > GetChannel < TChannel > ( long Channel , CancellationToken CancellationToken ) where TChannel : MainSocketChannel , new ( )
{
TChannel Return = new ( ) ;
switch ( Return )
2023-01-01 22:50:39 -05:00
{
2023-07-03 23:24:35 -04:00
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" ) ;
2023-01-01 22:50:39 -05:00
}
2023-07-03 23:24:35 -04:00
return Return ;
2023-01-01 22:50:39 -05:00
}
2023-07-03 23:24:35 -04:00
internal async Task < TChannel > GetChannel < TChannel > ( long id , JsonTypeInfo < TChannel > Json , CancellationToken CancellationToken ) where TChannel : MainSocketChannel , new ( )
2023-01-01 22:50:39 -05:00
{
2023-07-03 23:24:35 -04:00
TChannel request ;
if ( chans . Count > 0 & & chans . Any ( s = > s . Id = = id ) )
{
return chans . Where ( s = > s is TChannel & & s . Id = = id ) . Cast < TChannel > ( ) . FirstOrDefault ( ) ! ;
}
while ( true )
2023-01-01 22:50:39 -05:00
{
2023-07-03 23:24:35 -04:00
if ( CanRequest )
2023-01-01 22:50:39 -05:00
{
2023-07-03 23:24:35 -04:00
request = await GetFromServer ( $"SocketChannel/Get/{id}" , Json , CancellationToken ) ;
break ;
2023-01-01 22:50:39 -05:00
}
2023-07-03 23:24:35 -04:00
}
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 ) )
2023-01-01 22:50:39 -05:00
{
2023-07-03 23:24:35 -04:00
foreach ( MainSocketChannel ? p in chans . Where ( s = > s . Id = = request . Id ) )
{
chans . Remove ( p ) ;
}
2023-01-01 22:50:39 -05:00
}
2023-07-03 23:24:35 -04:00
chans . Add ( request ) ;
return request ;
2023-01-01 22:50:39 -05:00
}
2023-07-03 23:24:35 -04:00
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}'" ) ,
} ;
2023-01-01 22:50:39 -05:00
}
2023-07-03 23:24:35 -04:00
public async Task < SocketMessage > GetMessage ( long id , CancellationToken CancellationToken )
2023-01-01 22:50:39 -05:00
{
2023-07-03 23:24:35 -04:00
SocketMessage message ;
while ( true )
2023-01-01 22:50:39 -05:00
{
2023-07-03 23:24:35 -04:00
if ( CanRequest )
2023-01-01 22:50:39 -05:00
{
2023-07-03 23:24:35 -04:00
message = await GetFromServer ( "socketmessage" ,
SocketMessageContext . Default . SocketMessage ,
CancellationToken ,
new System . Collections . Generic . KeyValuePair < string , string? > ( "msg_id" , id . ToString ( ) ) ) ;
break ;
}
2023-01-01 22:50:39 -05:00
}
2023-07-03 23:24:35 -04:00
if ( message is not null ) return message ;
throw new Exception ( "Server did not return a message" ) ;
2023-01-01 22:50:39 -05:00
}
2023-07-03 23:24:35 -04:00
2023-01-01 22:50:39 -05:00
/// <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>
2023-07-03 23:24:35 -04:00
public async Task < Task > UpdateStatus ( UserStatus Status , CancellationToken CancellationToken )
2023-01-01 22:50:39 -05:00
{
2023-07-03 23:24:35 -04:00
IncomingHTTP ? data = await SendServer ( "SocketUserProfile/Status" , new Status ( ) { UserStatus = Status } , StatusContext . Default . Status , IncomingHTTPContext . Default . IncomingHTTP , CancellationToken ) ;
2023-01-01 22:50:39 -05:00
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" ) ;
}
2023-07-03 23:24:35 -04:00
( User as SocketUserBase ) ! . Status = Status ;
2023-01-01 22:50:39 -05:00
return Task . CompletedTask ;
}
2023-07-03 23:24:35 -04:00
internal async Task < Tuser > GetUser < Tuser > ( long UserId , JsonTypeInfo < Tuser > Json , CancellationToken CancellationToken ) where Tuser : SocketUserBase , new ( )
2023-01-01 22:50:39 -05:00
{
2023-07-03 23:24:35 -04:00
Tuser user ;
if ( poeople . Count > 0 & & poeople . Any ( s = > s . Id = = UserId ) )
2023-01-01 22:50:39 -05:00
{
2023-07-03 23:24:35 -04:00
Tuser temp = poeople . Where ( s = > s is Tuser & & s . Id = = UserId ) . Cast < Tuser > ( ) . FirstOrDefault ( ) ! ;
return temp ;
2023-01-01 22:50:39 -05:00
}
2023-07-03 23:24:35 -04:00
while ( true )
2023-01-01 22:50:39 -05:00
{
2023-07-03 23:24:35 -04:00
if ( CanRequest )
{
user = await GetFromServer ( "socketuser" ,
Json ,
CancellationToken ,
new KeyValuePair < string , string? > ( "id" , UserId . ToString ( ) ) ) ;
2023-01-01 22:50:39 -05:00
break ;
2023-07-03 23:24:35 -04:00
}
2023-01-01 22:50:39 -05:00
}
2023-07-03 23:24:35 -04:00
if ( user is null ) throw new Exception ( "Server did not return a user" ) ;
if ( poeople . Count > 0 & & poeople . Any ( s = > s . Id = = UserId ) )
2023-01-01 22:50:39 -05:00
{
2023-07-03 23:24:35 -04:00
foreach ( IUser ? p in poeople . Where ( s = > s . Id = = UserId ) )
{
poeople . Remove ( p ) ;
}
2023-01-01 22:50:39 -05:00
}
2023-07-03 23:24:35 -04:00
poeople . Add ( user ) ;
return user ;
2023-01-01 22:50:39 -05:00
}
2023-07-03 23:24:35 -04:00
public void SendServer < Tvalue > ( Tvalue Payload , JsonTypeInfo < Tvalue > jsonTypeInfo ) where Tvalue : IncomingWSS
2023-01-01 22:50:39 -05:00
{
ServerOut ? . Send ( JsonSerializer . Serialize ( Payload , jsonTypeInfo ) ) ;
}
2023-07-03 23:24:35 -04:00
public HttpResponseMessage GetFromServer ( string Path , CancellationToken CancellationToken , params KeyValuePair < string , string? > [ ] Headers )
2023-01-01 22:50:39 -05:00
{
using HttpClient web = new ( ) ;
web . Timeout = TimeSpan . FromSeconds ( 10 ) ;
if ( ! login ) web . DefaultRequestHeaders . Add ( "token" , Token ) ;
if ( Headers is not null & & Headers . Length > 0 ) foreach ( KeyValuePair < string , string? > header in Headers ) web . DefaultRequestHeaders . Add ( header . Key , header . Value ) ;
2023-07-03 23:24:35 -04:00
return web . GetAsync ( $"https://{Domain}/{ApiVersion}/{Path}" , cancellationToken : CancellationToken ) . Result ;
2023-01-01 22:50:39 -05:00
}
2023-07-03 23:24:35 -04:00
public Task GetFromServer ( string Path , string File , CancellationToken CancellationToken , params KeyValuePair < string , string? > [ ] Headers )
2023-01-01 22:50:39 -05:00
{
using HttpClient web = new ( ) ;
web . Timeout = TimeSpan . FromMinutes ( 10 ) ;
if ( ! login ) web . DefaultRequestHeaders . Add ( "token" , Token ) ;
if ( Headers is not null & & Headers . Length > 0 ) foreach ( KeyValuePair < string , string? > header in Headers ) web . DefaultRequestHeaders . Add ( header . Key , header . Value ) ;
2023-07-03 23:24:35 -04:00
HttpResponseMessage Response = web . GetAsync ( $"https://{Domain}/{ApiVersion}/{Path}" , CancellationToken ) . Result ;
Stream stream = Response . Content . ReadAsStreamAsync ( CancellationToken ) . Result ;
2023-01-01 22:50:39 -05:00
using FileStream fs = System . IO . File . Create ( File ) ;
stream . CopyTo ( fs ) ;
return Task . CompletedTask ;
}
2023-07-03 23:24:35 -04:00
public async Task < Tresult > GetFromServer < Tresult > ( string Path , JsonTypeInfo < Tresult > Type , CancellationToken CancellationToken , params KeyValuePair < string , string? > [ ] Headers ) where Tresult : IncomingHTTP , new ( )
2023-01-01 22:50:39 -05:00
{
2023-07-03 23:24:35 -04:00
HttpResponseMessage ServerResponce = GetFromServer ( Path , CancellationToken , Headers ) ;
2023-01-01 22:50:39 -05:00
if ( ! ServerResponce . IsSuccessStatusCode ) return new Tresult ( ) { StatusCode = ServerResponce . StatusCode , Error = ErrorCode . ServerError , ErrorMessage = $"Server responded with status code {(int)ServerResponce.StatusCode}:{ServerResponce.StatusCode}" } ;
2023-07-03 23:24:35 -04:00
Tresult ? temp = JsonSerializer . Deserialize ( ServerResponce . Content . ReadAsStreamAsync ( CancellationToken ) . Result , Type ) ;
2023-01-01 22:50:39 -05:00
if ( temp is null ) return new Tresult ( ) { StatusCode = ServerResponce . StatusCode , Error = ErrorCode . ServerError , ErrorMessage = $"Server responded with empty data" } ;
return temp ;
}
2023-07-03 23:24:35 -04:00
public async Task < Tresult > SendServer < Tvalue , Tresult > ( string Path , Tvalue Payload , JsonTypeInfo < Tvalue > jsonTypeInfo , JsonTypeInfo < Tresult > ReturnjsonTypeInfo , CancellationToken CancellationToken , params KeyValuePair < string , string? > [ ] Headers ) where Tvalue : IWebRequest where Tresult : IncomingHTTP , new ( )
2023-01-01 22:50:39 -05:00
{
using HttpClient web = new ( ) ;
if ( ! login ) web . DefaultRequestHeaders . Add ( "token" , Token ) ;
if ( Headers is not null & & Headers . Length > 0 ) foreach ( KeyValuePair < string , string? > header in Headers ) web . DefaultRequestHeaders . Add ( header . Key , header . Value ) ;
2023-07-03 23:24:35 -04:00
HttpResponseMessage ServerResponce = web . PostAsJsonAsync ( $"https://{Domain}/{ApiVersion}/{Path}" , Payload , jsonTypeInfo , CancellationToken ) . Result ;
2023-01-01 22:50:39 -05:00
if ( ! ServerResponce . IsSuccessStatusCode ) return new Tresult ( ) { StatusCode = ServerResponce . StatusCode , Error = ErrorCode . ServerError , ErrorMessage = $"Server responded with status code {(int)ServerResponce.StatusCode}:{ServerResponce.StatusCode}" } ;
Tresult error = new ( ) { StatusCode = ServerResponce . StatusCode , Error = ErrorCode . ServerError , ErrorMessage = $"Server responded with empty data" } ;
2023-07-03 23:24:35 -04:00
if ( string . IsNullOrWhiteSpace ( ServerResponce . Content . ReadAsStringAsync ( CancellationToken ) . Result ) ) return error ;
2023-01-01 22:50:39 -05:00
try
{
2023-07-03 23:24:35 -04:00
Tresult ? temp = JsonSerializer . Deserialize ( ServerResponce . Content . ReadAsStreamAsync ( CancellationToken ) . Result , ReturnjsonTypeInfo ) ;
2023-01-01 22:50:39 -05:00
if ( temp is null ) return error ;
return temp ;
}
catch { return error ; }
}
2023-07-03 23:24:35 -04:00
public async Task < Tresult > SendServer < Tresult > ( string Path , string File , JsonTypeInfo < Tresult > ReturnjsonTypeInfo , CancellationToken CancellationToken , params KeyValuePair < string , string? > [ ] Headers ) where Tresult : IncomingHTTP , new ( )
2023-01-01 22:50:39 -05:00
{
var fs = System . IO . File . OpenRead ( File ) ;
try
{
using HttpClient web = new ( ) ;
if ( ! login ) web . DefaultRequestHeaders . Add ( "token" , Token ) ;
web . Timeout = new TimeSpan ( 0 , 10 , 0 ) ;
if ( Headers is not null & & Headers . Length > 0 ) foreach ( KeyValuePair < string , string? > header in Headers ) web . DefaultRequestHeaders . Add ( header . Key , header . Value ) ;
2023-07-03 23:24:35 -04:00
HttpResponseMessage ServerResponce = web . PostAsync ( $"https://{Domain}/{ApiVersion}/{Path}" , new StreamContent ( fs ) , CancellationToken ) . Result ;
2023-01-01 22:50:39 -05:00
if ( ! ServerResponce . IsSuccessStatusCode ) return new Tresult ( ) { StatusCode = ServerResponce . StatusCode , Error = ErrorCode . ServerError , ErrorMessage = $"Server responded with status code {(int)ServerResponce.StatusCode}:{ServerResponce.StatusCode}" } ;
try
{
2023-07-03 23:24:35 -04:00
Tresult ? temp = JsonSerializer . Deserialize ( ServerResponce . Content . ReadAsStreamAsync ( CancellationToken ) . Result , ReturnjsonTypeInfo ) ;
2023-01-01 22:50:39 -05:00
if ( temp is null ) return new Tresult ( ) { StatusCode = ServerResponce . StatusCode , Error = ErrorCode . ServerError , ErrorMessage = $"Server responded with empty data" } ;
return temp ;
}
catch { return new Tresult ( ) { StatusCode = ServerResponce . StatusCode , Error = ErrorCode . ServerError , ErrorMessage = $"Server responded with empty data" } ; }
}
finally
{
fs . Close ( ) ;
}
}
2023-07-03 23:24:35 -04:00
}