GithubHelp home page GithubHelp logo

rrainn / lemmy-swift-client Goto Github PK

View Code? Open in Web Editor NEW
44.0 44.0 11.0 223 KB

A Swift client for Lemmy.

Home Page: https://rrainn.github.io/Lemmy-Swift-Client/documentation/lemmy_swift_client/

License: MIT License

Swift 95.56% Makefile 0.03% JavaScript 4.40%

lemmy-swift-client's People

Contributors

ckaik avatar creekdrops avatar fishcharlie avatar mdhiggins avatar thenoim 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

lemmy-swift-client's Issues

Make Request properties `var` instead of `let`

There is no reason the following code should be invalid:

let instance = LemmyAPI(baseUrl: url)

let siteRequest = GetSiteRequest()
siteRequest.auth = jwt

let siteResponse = try await instance.request(siteRequest)

But that code currently produces an error: Cannot assign to property: 'auth' is a 'let' constant.

We should make all those properties var instead of let to allow that code to be valid.

Non-string types are not included in the URL parameters for GET requests

Started playing around with this API tonight and noticed an issue

Any parameter from any of the Codable objects that's not a string is not included in the queryItems for the URLRequest

The issue comes from this code

request.url = request.url?.appending(queryItems: mirror.children.compactMap { (label, value) in
guard let label, let valueString = value as? String else { return nil }
return URLQueryItem(name: label, value: valueString)
})

Casting the value as String always returns nil for all the datatypes that aren't a String (int/enums, etc)

This gets a little more annoying to fix too as Mirror returns non-nil value even when nil so using String(describing: value) doesn't work either

One option would be to cast to CustomStringConvertible but you would also need to make all your enums conform to this protocol to work, which I guess wouldn't be that difficult

The other option which is working in my quick testing is to just serialize it to JSON and then use String(describing: value) like this

			request.url = request.url?.appending(queryItems: mirror.children.compactMap { (label, value) in
			let encoder = JSONEncoder()
			if let data = try? encoder.encode(apiRequest), let jsonObject = try? JSONSerialization.jsonObject(with: data, options: []), let parameters = jsonObject as? [String: Any?] {
				request.url = request.url?.appending(queryItems: parameters.compactMap { key, value in
					guard let value else { return nil }
					return URLQueryItem(name: key, value: String(describing: value))
				})
			}

Happy to put together a pull request for either approach

Handle different versions of Lemmy Server

Lemmy 0.18.0 to 0.18.3 removed a required property in the API, which caused decoding to fail. It feels like the Lemmy API is incredibly unstable between versions.

We need to figure out how to make this more stable and not throw errors between different server versions.

Some ideas:

  • Make every property optional
  • Have defaults for each property if decoding fails (ie. empty strings if decoding fails)

Any suggestions on how the community would like to see this handled would be appreciated.

Error Handling

Hi there!

I am building a Lemmy client for macOS using this package. (awesome work, by the way!!)

The only problem is, I cannot find out how to handle errors properly. This is what I have now:

    func login(username: String, password: String) async throws -> LoginResponse {
        var req = LoginRequest(username_or_email: username, password: password)
        if let response = try? await api.request(req) {
            UserDefaults.standard.set("LoggedIN", forKey: "login_temp") // Temporary Placeholder
            return response
        } else {
            throw LoginError(message: "Login failed: Check your username and password") // see footnote
        }
    }

1

I really don't like using functions with throws - it just complicates things in my opinion. Is there another way?

Thanks!

Footnotes

  1. LoginError is a simple struct with a message key as a string, which extends to error. โ†ฉ

GetPostResponse broken?

GetPostRequest causes JSON decode error because what it's decoding to doesn't match the API response

API response
image

What it tries to decode to
image

Decoder error says "key online isn't found" or something like that

Support Lemmy v0.18.0

Lemmy v0.18.0 was released today.

According to the post:

  • There are two breaking changes since the last release:
    • GetSite.taglines is now required, and is an empty array.
    • SortType and ListingType are now numbered enums, rather than strings in some places, and numbers in others.

A full comparison of the changes can be found here.

It is very unclear at this point how the Lemmy API is versioned. The expectation (although I don't believe documented anywhere) is that breaking API changes would bump the version in the API path. This was not the case with the release of Lemmy 0.18.0.

I have posted a comment in reply to @dessalines's Lemmy post requesting clarification on how Lemmy is viewing API versioning.

An API like this that is designed to be used externally, needs some type of solid versioning system, because you don't know what server you are talking to and what version they are running until you run GetSiteRequest.


I'm still trying to figure out the best way to handle these breaking changes within this package. If anyone has any feedback or advice, I would love to hear it.

Consideration: Make all data types conform to Hashable

This might already be something already being considered and worked on, but I figured I would weigh in if not. As of right now, not having types such as PostView, CommentView, etc. conform to hashable can be a bit limiting for iteration and usage within the NavigationStack. I'm willing to take this on and commit, but I wanted to get your guys thoughts before doing so.

keyNotFound when calling GetPostsRequest()

I get this error when calling GetPostsRequest() in my attempts to build a Feed :

_Unexpected error getting feed: keyNotFound(CodingKeys(stringValue: "inbox_url", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "posts", intValue: nil), JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "creator", intValue: nil)], debugDescription: "No value associated with key CodingKeys(stringValue: "inbox_url", intValue: nil) ("inbox_url").", underlyingError: nil)).

There is no way to pass the "inbox_url" parameter in the GetPostRequest struct.

Mock Responses

Currently there is no good way to mock responses in this library for testing purposes.

Not quite sure the best way to handle this. Here are some initial thoughts tho:

  1. We could add protocols representing each response that things can conform to. Which would make it easy for users to create structs that conform to those protocols. ex. GetSiteResponse conforms to GetSiteResponseProtocol. And a user of this library could create a MockGetSiteResponse that conforms to GetSiteResponseProtocol. And they could use GetSiteResponseProtocol as the type and pass in a GetSiteResponse or MockGetSiteResponse`.
  2. We could just add public initializers to all the responses that allow initialization by passing in parameters into the init.

Does anyone have any thoughts on the best path forward here? Any other suggestions of ideas we should consider?

Decoding issues when working with enterprise.lemmy.ml

I've been trying out this client with the enterprise.lemmy.ml instance which is listed here as a lemmy instance for testing purposes.

I haven't gotten far but I did run into some issues when sending GetSiteRequest and I figured I'd check in before doing work and submitting a PR for this since I'm not entirely sure if these issues even should be handled.

Here's what I've run into when running sending a GetSiteRequest to https://enterprise.lemmy.ml/api/v3:

  1. On that instance the admins seem to be missing an inbox_url in their PersonSafe. Which is correctly implemented by Lemmy-Swift-Client since according to the documentation, inbox_url is not optional. However since it's missing there's no way to work with that instance. Documentation
  2. The same is true for GetSiteResponse and its online property, which is also missing on that instance. Documentation
  3. And finally for the federation_debug property on LocalSite. Documentation

There's one more issue though about the RegistrationMode enum, used for the registration_mode property on LocalSite. Currently the .open has the string value of open. However in this specific instance the server actually returns Open and therefore decoding fails.

E.g. adding a custom decoding initializer to RegistrationMode fixes the issue.

public init(from decoder: Decoder) throws {
	let container = try decoder.singleValueContainer()
	let value = try container.decode(String.self)

	guard let mode = RegistrationMode(rawValue: value.lowercased()) else {
		throw DecodingError.dataCorrupted(.init(
			codingPath: decoder.codingPath,
			debugDescription: "could not extract registration mode"
		))
	}

	self = mode
}

Note: this does have the caveat of requiring rawValues for all cases to be fully lowercased.

I guess this is a question of Accuracy vs Compatibility.

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.