Giter VIP home page Giter VIP logo

ghostsharp's Introduction

CI Build License: MIT NuGet CodeFactor Open Source Helpers Language Twitter

GhostSharp

This is a wrapper around v5.0 of the Content and Admin APIs. They are RESTful JSON APIs built into the core of the Ghost blogging platform. Check out the official Ghost API docs and read a little about my experience using them.

Usage

Accessing the Content API

If you need to access the Content API, all you need is the URL of your site and a Content API Key, available on the "Integrations" page. Once you have those pieces of information, you can access any "public" content.

var ghost = new GhostSharp.GhostContentAPI("https://grantwinney.com", "a6d33f1b95ff17adf0f787a70a");
var settings = ghost.GetSettings();

Console.WriteLine($"Welcome to {settings.Title}: {settings.Description}\r\n");
Console.WriteLine($"Navigation: {string.Join(", ", settings.Navigation.Select(x => x.Label))}");

Output:

Welcome to Grant Winney: We learn by doing. We've all got something to contribute.

Navigation: Home, APIs, Lambda, Rasp PI, About Me, CV

Accessing the Admin API

If you need to access the Admin API, all you need is the URL of your site and an Admin API Key, also available on the "Integrations" page. Once you have those pieces of information, you can access any "private" content.

var ghost = new GhostSharp.GhostAdminAPI("https://grantwinney.com", 
    "5cf706fd7d4a33066550627a:9e5ed2b90e40f68573b0ccaf4aef666b047fc9867ad285b2e219eed5503bae53");
var site = ghost.GetSite();

Console.WriteLine($"Welcome to <a href='{site.Url}'>{site.Title}</a>\r\n");
Console.WriteLine($"Running Ghost v{site.Version}");

Output:

Welcome to <a href='https://grantwinney.com/'>Grant Winney</a>

Running Ghost v2.23

You can optionally pass in a version number for the API (i.e. 4.0), or omit it to default to the latest (currently 5.0). I'm only able to support one version (due to there only being 24 hours in a day), but setting that to a lesser value may work in some cases too.

Running the Tests

The tests are setup to run against an actual instance of the Ghost blog, using a valid API key. There are details in the TestBase.cs class that you'll need to fill in, such as a valid API key, valid post ID, valid post slug, etc, etc.

Problems?

Open an issue, and include errors, unexpected behavior, steps to reproduce, etc. The more details, the better!

Feel free to open a PR if you figure out how to fix it.

Ideas?

Open an issue. I can't promise when new features or suggestions will get implemented, but I'll check them out.

Release Notes

  • 2.0.0 - ⭐ Upgraded to .NET 6 and API v5. Implemented the stable endpoints, except for members.
  • 1.0.9 - 🐛 Noticed that pages aren't being created; other refactoring.
    Breaking change: Eliminated Page in favor of a single Post object again, for simplicity. The split wasn't necessary as a Page is just a Post that doesn't end up in feeds. Also, a few fields in a Post don't play nicely when creating pages, but I figured out a different way to omit those.
  • 1.0.8 - 🐛 Several fields marked as updateable that aren't. (thx for the heads up @unnanego)
    Breaking change: This led to a larger refactoring, which might break some current implementations. Properties in the Post class that cannot be changed now have private setters (instead of just an attribute on them). The Page class was completely separated from the Post class, so RestSharp could correctly deserialize objects coming from Ghost.
  • 1.0.7 - ⭐ Implement the Themes admin endpoint. (thx for pointing me in the right direction @naz)
  • 1.0.6 - ⭐ Implement API v3.
  • 1.0.4 - 🧹 Code cleanup. Added license to NuGet package.
  • 1.0.3 - ⭐ Implement Admin API v2 endpoints (posts, pages, images, site)
    Breaking change: GhostAPI is now split into GhostContentAPI and GhostAdminAPI
  • 1.0.1 - 🧹 Added comments to aid in intellisense.
  • 1.0.0 - ⭐ Implement Content API endpoints.

ghostsharp's People

Stargazers

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

Watchers

 avatar  avatar

ghostsharp's Issues

Possibly add function for using the refresh token

There are function in the library for getting an auth record, which includes an auth token and a refresh token.

There are rules around how long each are good... I think the auth token is a month but the refresh token is 6 months maybe?

Might want to add a function that allows the refresh token to be used to refresh the auth token.

Support short form of Authors and Tags?

There's a short form for tags and authors, but supporting it in C# is more complicated than in JavaScript, where the types are made up and the fields don't matter.

You can link tags and authors to any post you create in the same request body, using either short or long form to identify linked resources.

Short form uses a single string to identify a tag or author resource. Tags are identified by name and authors are identified by email address:

{
    "posts": [{
        "title": "My test post",
        "tags": ["Getting Started", "Tag Example"],
        "authors": ["[email protected]", "[email protected]"]
    }]
}

I didn't implement it yet, but if there was a strong reason to, then I'd do something about it... maybe.

More detailed error messages

The RestResponse.Content field looks something like this when it has an error in it, when it's returned in GhostAPI.cs. I could modify the error I return to take some of that data into account, to make errors more meaningful...

{
	"errors": [{
		"message": "Validation error, cannot save post.",
		"context": "Validation failed for 'posts'",
		"type": "ValidationError",
		"details": [{
				"keyword": "additionalProperties",
				"dataPath": "",
				"schemaPath": "#/additionalProperties",
				"params": {
					"additionalProperty": "Posts"
				},
				"message": "should NOT have additional properties"
			},
			{
				"keyword": "required",
				"dataPath": "",
				"schemaPath": "#/required",
				"params": {
					"missingProperty": "posts"
				},
				"message": "should have required property 'posts'"
			}
		],
		"property": "posts",
		"help": null,
		"code": null,
		"id": "b50a7fd0-500a-11e9-a8e0-472301ed00b2"
	}]
}




{
	"errors": [{
		"message": "Validation error, cannot edit post.",
		"context": "Validation failed for 'posts[0]'",
		"type": "ValidationError",
		"details": [{
			"keyword": "additionalProperties",
			"dataPath": ".posts[0]",
			"schemaPath": "#/additionalProperties",
			"params": {
				"additionalProperty": "uuid"
			},
			"message": "should NOT have additional properties"
		}, {
			"keyword": "additionalProperties",
			"dataPath": ".posts[0]",
			"schemaPath": "#/additionalProperties",
			"params": {
				"additionalProperty": "comment_id"
			},
			"message": "should NOT have additional properties"
		}],
		"property": "posts[0]",
		"help": null,
		"code": null,
		"id": "1ba48e70-5155-11e9-be0e-1702dc9d57c3"
	}]
}

The byte conversion code in the auth flow can now be replaced by a built-in method

This snippet of code:

public static byte[] StringToByteArray(string hex)
{
int NumberChars = hex.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
return bytes;
}

Is now natively supported in .NET 5 and up through:

Convert.FromHexString()

See:
https://learn.microsoft.com/en-us/dotnet/api/system.convert.fromhexstring?view=net-6.0&WT.mc_id=DOP-MVP-5001511

Most fields not transferring when creating a post

Most fields, like Html, PlainText, CustomExcerpt, CreatedTime, etc., should be transferred when creating a post, but they're not.

In fact, the Title is one of the few pieces that does transfer correctly.


also see: CreatePostTests.CreatePost_ReturnsPost_WhenPostCreated()

Publish GhostSharp as Nuget Package

I am planning to use GhostSharp as a dependency for a statistic site I am building using dotnetcore.

Unfortunately, GhostSharp is not yet available in NuGet.

I have already forked the repo and I am planning to put automatic versioning release to Nuget.

Will keep you posted.

Regards,
Rene

By the way, @grantwinney nice work

Create interfaces for all classes

Consider creating interfaces for all classes, to make it easier for others to mock things out (i.e. using the moq library) during testing.

Easiest to do this once I'm sure the library reasonably covers most of the Ghost API.

Resolve todo in Post.cs

            // TODO
            //if (string.IsNullOrEmpty(post.MobileDoc) && !string.IsNullOrEmpty(post.Html))
            //    request.AddQueryParameter("source", "html");

Still keep the UpdatedAt value the same?

In Endpoints/Admin/Post.cs I'm doing updatedPost.UpdatedAt = originalPost.UpdatedAt; to keep the UpdatedAt the same time. Is this still necessary? Maybe switch it to only prevent an older timestamp?

Support the mobiledoc section

It seems like the mobiledoc field of the posts request is something in and of itself, and I don't understand it yet. Need to look at the docs and update library to properly support it.

just some comments i had in the AdminAPI\IntegrationTests\UpdatePostIntgTests file

  • finish asserts in above test
  • is title ALWAYS required (I think it can't be left blank)?? are all writable fields required even if not changing?? :/
  • do a GET and save it right back in?
  • Tag and author relations will be replaced, not merged - test this
  • which takes precedence if html AND mobiledoc are both updated?
    • need to attach query parameter to specify html, like when creating post?
  • should i create a CreatableAttribute too to ignore fields that shouldn't be sent, like id or uuid?
  • !! then copy all of this for pages

codeinjection_head missing on getposts

Hi, I don't know if you still maintain this, but I figured it was worth a shot. I am using it and loving it, but I no matter what I do, I never get codeinjection_head back from the getposts or getpostbyid methods. I am getting this by making my own call, but I have made something that means that all my posts has it, so I need it for all of my update calls to not overwrite the values :D

Is there any chance you could get that working? :)

Support multiple image uploads

I think the images endpoint supports uploading multiple files at once. Could research and implement it, but probably won't unless someone asks for it.

This might also be true for themes too... maybe? (In both cases, the response that comes back from the API is a list of images/themes...)

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.