Giter Club home page Giter Club logo

oddity's Introduction

Oddity logo

NuGet Downloads Build Issues Stars License Doxygen

.NET wrapper for unofficial SpaceX API v4 (with full support for all endpoints and query subsystem), providing information about everything related to the company. Thanks to this library, you can easily get any data without messing with HTTP requests, JSON deserializators or constructing query bodies. You can use the following endpoints:

  • Capsules - detailed information about Dragon capsules.
  • Company - detailed information about SpaceX as a company.
  • Cores - detalied information about first stage cores.
  • Crew - detailed information about Dragon crew members.
  • Dragons - detailed information about Dragon capsule versions.
  • Landpads - detailed information about landing pads and ships.
  • Launches - detailed information about launches.
  • Launchpads - detailed information about launchpads.
  • Payloads - detailed information about launch payloads.
  • Roadster - detailed information about Elon's Tesla Roadster.
  • Rockets - detailed information about rocket versions.
  • Ships - detailed information about ships in the SpaceX fleet.
  • Starlink - detailed information about Starlink satellites and orbits.

To learn how to use this library, look at this set of examples:

  • OverviewApp - a test of all endpoints, lazy properties and cache. It's not a real app that does anything useful but allows us to introduce into library architecture.
  • UpcomingLaunchesApp - displays upcoming launches and the most important information about the next launch.
  • StarlinkApp - displays sample Starlink statistics: the lowest perigee, the highest apogee, the lowest velocity, the highest velocity.

Feel free to make issues or pull request to improve library - Oddity v2 has been rewritten from scratch and it can potentially contain some bugs.

Features

  • Smart models - allow us to retrieve linked models from API using lazy properties. No more manual picking objects using their IDs.
  • Support for query subsystem - v4 API has introduced the new query system (using mongoose-paginate) which allows user for more flexible queries. Oddity wraps it with the easy to use classes and provides the most important filters.
  • Internal cache - this is the nice addition to the smart models and their lazy properties - it allows to reduce the time needed for making and processing API requests by caching deserialized objects for a period specified in the API docs.

Installation

or

  • search "Oddity" in Package Manager

or

  • run Install-Package Oddity in the Package Manager Console

Minimal requirements

Library is built on .NET Standard 1.1 which contains support for:

  • .NET Framework 4.5 or higher
  • .NET Core 1.0 or higher
  • Mono 4.6 or higher
  • Xamarin.iOS 10.0 or higher
  • Xamarin.Mac 3.0 or higher
  • Xamarin.Android 7.0 or higher
  • Universal Windows Platform 10.0 or higher

External dependencies:

Example usage

using System;
using System.Threading.Tasks;
using Newtonsoft.Json.Serialization;
using Oddity;
using Oddity.Events;

namespace OverviewApp
{
    class Program
    {
        static async Task Main(string[] args)
        {
            var oddity = new OddityCore();

            // Optional
            oddity.OnDeserializationError += OddityOnDeserializationError;
            oddity.OnRequestSend += Oddity_OnRequestSend;
            oddity.OnResponseReceive += OddityOnResponseReceive;

            // Test of the /capsules endpoint
            var allCapsules = await oddity.CapsulesEndpoint.GetAll().ExecuteAsync();
            var capsule = await oddity.CapsulesEndpoint.Get("5e9e2c5bf35918ed873b2664").ExecuteAsync();
            var capsuleLaunch = capsule.Launches[0].Value;

            // Test of the /company endpoint
            var company = await oddity.CompanyEndpoint.Get().ExecuteAsync();

            // Test of the /cores endpoint
            var allCores = await oddity.CoresEndpoint.GetAll().ExecuteAsync();
            var core = await oddity.CoresEndpoint.Get("5e9e28a6f35918c0803b265c").ExecuteAsync();
            var coreLaunch1 = core.Launches[0].Value;
            var coreLaunch2 = core.Launches[1].Value;
            var coreLaunch3 = core.Launches[2].Value;
            var coreLaunch4 = core.Launches[3].Value;

            // Test of the /crew endpoint
            var allCrew = await oddity.CrewEndpoint.GetAll().ExecuteAsync();
            var crewMember = await oddity.CrewEndpoint.Get("5ebf1b7323a9a60006e03a7b").ExecuteAsync();
            var crewMemberLaunch = crewMember.Launches[0].Value;

            // Test of the /crew endpoint
            var crewLaunch = await oddity.LaunchesEndpoint.Get("5eb87d46ffd86e000604b388").ExecuteAsync();
            var crewLaunchCore = crewLaunch.Cores[0].Core.Value;
            var crewLaunchLandpad = crewLaunch.Cores[0].Landpad.Value;
            var crewLaunchRocket = crewLaunch.Rocket.Value;
            var crewLaunchCrew = crewLaunch.Crew[0].Value;
            var crewLaunchShip = crewLaunch.Ships[0].Value;
            var crewLaunchCapsule = crewLaunch.Capsules[0].Value;
            var crewLaunchPayload = crewLaunch.Payloads[0].Value;
            var crewLaunchLaunchpad = crewLaunch.Launchpad.Value;

            // Test of the /dragons endpoint
            var allDragons = await oddity.DragonsEndpoint.GetAll().ExecuteAsync();
            var dragon = await oddity.DragonsEndpoint.Get("5e9d058759b1ff74a7ad5f8f").ExecuteAsync();

            // Test of the /landpads endpoint
            var allLandpads = await oddity.LandpadsEndpoint.GetAll().ExecuteAsync();
            var landpad = await oddity.LandpadsEndpoint.Get("5e9e3032383ecb90a834e7c8").ExecuteAsync();
            var landpadLaunch = landpad.Launches[0].Value;

            // Test of the /launches endpoint
            var launch = await oddity.LaunchesEndpoint.Get("5eb87d44ffd86e000604b386").ExecuteAsync();
            var allLaunches = await oddity.LaunchesEndpoint.GetAll().ExecuteAsync();
            var pastLaunches = await oddity.LaunchesEndpoint.GetPast().ExecuteAsync();
            var upcomingLaunches = await oddity.LaunchesEndpoint.GetUpcoming().ExecuteAsync();
            var latestLaunch = await oddity.LaunchesEndpoint.GetLatest().ExecuteAsync();
            var nextLaunch = await oddity.LaunchesEndpoint.GetNext().ExecuteAsync();

            // Test of the /launches endpoint
            var commercialLaunch = await oddity.LaunchesEndpoint.Get("5eb87d46ffd86e000604b389").ExecuteAsync();
            var commercialLaunchCore = commercialLaunch.Cores[0].Core.Value;
            var commercialLaunchLandpad = commercialLaunch.Cores[0].Landpad.Value;
            var commercialLaunchFairingShips = commercialLaunch.Fairings.Ships[0].Value;
            var commercialLaunchRocket = commercialLaunch.Rocket.Value;
            var commercialLaunchShip = commercialLaunch.Ships[0].Value;
            var commercialLaunchPayload = commercialLaunch.Payloads[0].Value;
            var commercialLaunchLaunchpad = commercialLaunch.Launchpad.Value;

            // Test of the /launchpads endpoint
            var allLaunchpads = await oddity.LaunchpadsEndpoint.GetAll().ExecuteAsync();
            var launchpad = await oddity.LaunchpadsEndpoint.Get("5e9e4502f509092b78566f87").ExecuteAsync();
            var launchpadLaunch1 = launchpad.Launches[0].Value;
            var launchpadLaunch2 = launchpad.Launches[1].Value;
            var launchpadLaunch3 = launchpad.Launches[2].Value;
            var launchpadLaunch4 = launchpad.Launches[3].Value;
            var launchpadRocket = launchpad.Rockets[0].Value;

            // Test of the /payloads endpoint
            var allPayloads = await oddity.PayloadsEndpoint.GetAll().ExecuteAsync();
            var payload = await oddity.PayloadsEndpoint.Get("5eb0e4bbb6c3bb0006eeb1ed").ExecuteAsync();
            var payloadLaunch = payload.Launch.Value;
            var payloadCapsule = payload.Dragon.Capsule.Value;

            // Test of the /roadster endpoint
            var roadster = await oddity.RoadsterEndpoint.Get().ExecuteAsync();

            // Test of the /rockets endpoint
            var allRockets = await oddity.RocketsEndpoint.GetAll().ExecuteAsync();
            var rocket = await oddity.RocketsEndpoint.Get("5e9d0d95eda69974db09d1ed").ExecuteAsync();

            // Test of the /ships endpoint
            var allShips = await oddity.ShipsEndpoint.GetAll().ExecuteAsync();
            var ship = await oddity.ShipsEndpoint.Get("5ea6ed2e080df4000697c90a").ExecuteAsync();
            var shipLaunch1 = ship.Launches[0].Value;
            var shipLaunch2 = ship.Launches[1].Value;
            var shipLaunch3 = ship.Launches[2].Value;
            var shipLaunch4 = ship.Launches[3].Value;

            // Test of the /starlink endpoint
            var allStarlinks = await oddity.StarlinkEndpoint.GetAll().ExecuteAsync();
            var starlink = await oddity.StarlinkEndpoint.Get("5eed7716096e590006985825").ExecuteAsync();
            var starlinkLaunch = starlink.Launch.Value;

            // Test of the pagination
            var queryStarlink = await oddity.StarlinkEndpoint.Query()
                .WithFieldGreaterThan(p => p.SpaceTrack.Apoapsis, 500)
                .WithLimit(100)
                .SortBy(p => p.SpaceTrack.Apoapsis, false)
                .ExecuteAsync();
            await queryStarlink.GoToNextPage();
            await queryStarlink.GoToNextPage();
            await queryStarlink.GoToNextPage();
            await queryStarlink.GoToPrevPage();
            await queryStarlink.GoToPrevPage();
            await queryStarlink.GoToPrevPage();
            await queryStarlink.GoToLastPage();
            await queryStarlink.GoToFirstPage();

            // Test of cache
            var queryLaunch = await oddity.LaunchesEndpoint.Query().WithLimit(1).ExecuteAsync();
            var queryLaunchCached = await oddity.LaunchesEndpoint.Get("5eb87cd9ffd86e000604b32a").ExecuteAsync();

            var launchCached = await oddity.LaunchesEndpoint.Get("5eb87d44ffd86e000604b386").ExecuteAsync();
            var allLaunchesCached = await oddity.LaunchesEndpoint.GetAll().ExecuteAsync();
            var pastLaunchesCached = await oddity.LaunchesEndpoint.GetPast().ExecuteAsync();
            var upcomingLaunchesCached = await oddity.LaunchesEndpoint.GetUpcoming().ExecuteAsync();
            var latestLaunchCached = await oddity.LaunchesEndpoint.GetLatest().ExecuteAsync();
            var nextLaunchCached = await oddity.LaunchesEndpoint.GetNext().ExecuteAsync();

            Console.Read();
        }

        private static void OddityOnDeserializationError(object sender, ErrorEventArgs errorEventArgs)
        {
            Console.WriteLine("Something went wrong");

            // We don't want to stop program, just leave problematic field as null
            errorEventArgs.ErrorContext.Handled = true;
        }

        private static void Oddity_OnRequestSend(object sender, RequestSendEventArgs e)
        {
            Console.WriteLine($"Sending request... URL: {e.Url}");

            if (e.Query != null)
            {
                Console.WriteLine($"Query: {e.Query}");
            }
        }

        private static void OddityOnResponseReceive(object sender, ResponseReceiveEventArgs e)
        {
            Console.WriteLine($"Response received! Status code: {e.StatusCode}");
            Console.WriteLine($"Raw content: {e.Response}");
            Console.WriteLine();
        }
    }
}

Why Oddity?

https://www.youtube.com/watch?v=iYYRH4apXDo

Credits

Icon made by Freepik from www.flaticon.com

oddity's People

Contributors

itsmuntadhar avatar martindevans avatar tearth avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

oddity's Issues

Asynchronous support

Seeing the code call await ExecuteAsync().Result scared me ๐Ÿ˜ฒ (if you didn't know, calling .Result before the method is finished executing (because of the await) can cause asynchronous issues). A useful link: https://montemagno.com/c-sharp-developers-stop-calling-dot-result/

I can't help but ask how you feel about that, because it breaks the asynchronous pattern.
I'm happy to help with reworking the asynchronous infrastructure, especially because I would like to see fully asynchronous methods available to the user.

Solutions:

  • The idea of the Execute method on the BuilderBase class is definitely a good idea but it's sort of negating the point of the Task-based asynchronous pattern. It would be nice to see methods like Execute and ExecuteAsync, with the former using <AsyncMethodName>().GetAwaiter().GetResult() (the "correct" way to synchronously wait for async methods to complete) and the later using an async requests library
  • Similar to other APIs and libraries (for example, Discord.NET), pushing the Execute level up to the method is a good idea. For example, we could use GetNextAsync and GetNext directly on the builder class.

Incorrect values for ships

Hi! I discovered, that for ships, latitude, longitude and last update is incorrect.

On 6th September, for "American Champion" ship, according to website Marine Trafic, last update and data about position are provided. Can you fix it, please?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.