// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. #nullable disable using System; using System.Threading; using System.Threading.Tasks; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Online.API.Requests.Responses; using osu.Game.Users; namespace osu.Game.Online.API { public class DummyAPIAccess : Component, IAPIProvider { public const int DUMMY_USER_ID = 1001; public Bindable LocalUser { get; } = new Bindable(new APIUser { Username = @"Dummy", Id = DUMMY_USER_ID, }); public BindableList Friends { get; } = new BindableList(); public Bindable Activity { get; } = new Bindable(); public string AccessToken => "token"; public bool IsLoggedIn => State.Value == APIState.Online; public string ProvidedUsername => LocalUser.Value.Username; public string APIEndpointUrl => "http://localhost"; public string WebsiteRootUrl => "http://localhost"; public int APIVersion => int.Parse(DateTime.Now.ToString("yyyyMMdd")); public Exception LastLoginError { get; private set; } /// /// Provide handling logic for an arbitrary API request. /// Should return true is a request was handled. If null or false return, the request will be failed with a . /// public Func HandleRequest; private readonly Bindable state = new Bindable(APIState.Online); private bool shouldFailNextLogin; /// /// The current connectivity state of the API. /// public IBindable State => state; public DummyAPIAccess() { LocalUser.BindValueChanged(u => { u.OldValue?.Activity.UnbindFrom(Activity); u.NewValue.Activity.BindTo(Activity); }, true); } public virtual void Queue(APIRequest request) { Schedule(() => { if (HandleRequest?.Invoke(request) != true) { request.Fail(new InvalidOperationException($@"{nameof(DummyAPIAccess)} cannot process this request.")); } }); } public void Perform(APIRequest request) => HandleRequest?.Invoke(request); public Task PerformAsync(APIRequest request) { HandleRequest?.Invoke(request); return Task.CompletedTask; } public void Login(string username, string password) { state.Value = APIState.Connecting; if (shouldFailNextLogin) { LastLoginError = new APIException("Not powerful enough to login.", new ArgumentException(nameof(shouldFailNextLogin))); state.Value = APIState.Offline; shouldFailNextLogin = false; return; } LastLoginError = null; LocalUser.Value = new APIUser { Username = username, Id = 1001, }; state.Value = APIState.Online; } public void Logout() { LocalUser.Value = new GuestUser(); state.Value = APIState.Offline; } public IHubClientConnector GetHubConnector(string clientName, string endpoint, bool preferMessagePack) => null; public RegistrationRequest.RegistrationRequestErrors CreateAccount(string email, string username, string password) { Thread.Sleep(200); return null; } public void SetState(APIState newState) => state.Value = newState; IBindable IAPIProvider.LocalUser => LocalUser; IBindableList IAPIProvider.Friends => Friends; IBindable IAPIProvider.Activity => Activity; public void FailNextLogin() => shouldFailNextLogin = true; } }