kekolab / javaplex

A java library to interact with the Plex Media Server
0 stars 1 forks source link

How can I properly PR a code change/how can I help? #3

Closed JZomDev closed 8 months ago

JZomDev commented 8 months ago

I am really liking this project as it helps my idea of a discord bot I am working on and replacing the python based bot with a java bot (because i know java more, and it's fun to code for fun)

I don't want to keep asking you to add features because I can do them myself but I don't quite understand)

The naming conventions of a file How the whole Serialzing stuff (this response is XML format, not json) Probably more things I don't get too tbh.

I want to add https://plex.tv/api/servers//shared_servers?X-Plex-Token=TOKEN

What it is:

It supports GET which gets the list of users you're sharing with and the libraries they have access to. I do not have an example format handy.

This same endpoint also supports POST which allows you to provide an email and the library sections you want to share and it will send a friend request to it.

String requestBody = "{" +
            "  \"server_id\": \"\"," +
            "  \"shared_server\": {\"library_section_ids\" : " + sections.toString() + ", \"invited_email\": \"" + invitedEmail + "\"}," +
            "  \"sharing_settings\":" +
            "  {" +
            "    \"allowSync\": \"0\"," +
            "    \"allowCameraUpload\": \"0\"," +
            "    \"allowChannels\": \"0\"," +
            "    \"filterMovies\": {}," +
            "    \"filterTelevision\": {}," +
            "    \"filterMusic\": {}" +
            "  }" +
            "}"

I can do the postman type of work to understand the object but not the practice you're doing to make it the way it is here but the resource I got help from to understand the get/post available was from the plex python lib and the specific code I referred to is found here https://python-plexapi.readthedocs.io/en/latest/_modules/plexapi/myplex.html#MyPlexAccount.inviteFriend

I don't need you to implement it, I can do it but I'd like help doing it correctly if possible. The project isn't something I am familiar with. but I would like to help!

you can contact me on discord if that's more helpful to chat @redrumze there.

kekolab commented 8 months ago

I am really liking this project as it helps my idea

First things first: really thank you. Alas you've stumbled upon a (for me) quite old quick-and-dirty library which I wrote to create a Plex Skill for Alexa which does not exist in my country. Recently I've open-sourced it making the repo public and I would've never though somebody would actually use it 😄

Being a quite personal project, I used it also to improve my skills and style... basically to improve my skills (I haven't been working as a programmer for a very very long time, but I like coding). You've experienced how not jitpack-compliant it was when you discovered it.

The naming conventions of a file

Basically, there's none... or at least not a structured one. To make things more fun, I do not always return the "MediaContainer", but, sometimes, the content of the MediaContainer. For example, the endpoint /library/sections/{id}/all is not mapped to a MediaContainer class, but directly to it's content (the list of the items in the library section). I chose so because the MediaContainer wrapping the item list does not have any value-added information (you can see it here). Sometimes I choose exactly the opposite (e.g. /status) which is mapped to its own PlexStatus although it's quite useless. I could have created something like PlexMediaServer.statusSessions() instead of using PlexMediaServer.status().sessions(), but I chose to do so:

How the whole Serialzing stuff (this response is XML format, not json)

The deserialization is completely delegated to Jackson. The responses received from the server are JSON. This is accomplished by adding the Accept: application/json the the request sent to the server (it is done here: I add an interceptor which adds all the headers to any request). Why did I choose to force the JSON response? Because it is somewhat "cleaner", mainly with boolean values which, in XML format, are sometimes returned as integer 0/1, sometimes as strings "0"/"1", sometimes "true"/"false". This forced me to write a ton of custom deserializers (in package mappers). The JSON response always uses boolean values true/false.

Anyway, for some requests the server in the past returned me an XML (although recently I've seen less and less XML responses and the Accept header in the request is much more respected). This is why in the PlexHttpClient class there are two ObjectMappers (i.e. serializers/deserializers): one for XML and one for JSON. The first one is used to deserialize in case the response has the header Content-Type : application/xml while the second one is used in case the response has the header Content-Type set to application/json (the responsible method is: this one).

Same thing for the X-Plex-Token uri parameter; it is automatically added to any request here

Probably more things I don't get too tbh.

Not to mention the ones I do not even remember myself 🤣

It supports GET which gets the list of users you're sharing with and the libraries they have access to. I do not have an example format handy.

Oh... you have a plex pass. That's cool. Or at least you're thinking about somebody who has it.

I want to add https://plex.tv/api/servers/<machine_id>/shared_servers?X-Plex-Token=TOKEN

Mm... once upon a time I did support the endpoint https://plex.tv/api/servers, then I dropped it as it was no-use to me 🤣

It supports GET which gets the list of users you're sharing with and the libraries they have access to. I do not have an example format handy.

That's bad... not having the actual response exposes us to possible deserialization errors

This same endpoint also supports POST which allows you to provide an email and the library sections you want to share and it will send a friend request to it.

OK. We have to choices here:

  1. The better way 1.1. Create an object with the all the properties and getters and setters 1.2. Create a method in PlexHttpClient that handles all the POST requests and delegates to Jackson the serialization of the object
  2. The ugly way 2.1. Something like you have done (no offense), and I have done here (although here it is with query parameters and not with the body).

you can contact me on discord if that's more helpful to chat @redrumze there.

First I had to understand what discord is... Anyway, you are not accepting friend requests. I have created an account here: @kekolab. Feel free to add me.

JZomDev commented 8 months ago

Oh... you have a plex pass. That's cool. Or at least you're thinking about somebody who has it.

Yes I do have it, I didn't know some of the APIs I was maybe trying to leverage are because I paid for it! I do not want to introduce paid tier end points unless they're obvious they're paid for.

The ugly way 2.1. Something like you have done (no offense), and I have done here (although here it is with query parameters and not with the body).

None taken, I've tried cleaning it up but without knowing the "correct" way it's hard to discern that from the way that just gets it to work.

If you could, I've made various code changes in a PR I submitted shortly after asking this question but would like feedback on the wrong (in terms of scope of project or direction i took), because when testing my .jar i generate from the project with my code it does do what i want it do so it at least works. it's just got a different look-and-feel from the code you've previously written.

I really am enjoying exploring and trying things that I've not done through this project, hope we can work together or at least I can work and you review. :)

JZomDev commented 8 months ago

That's bad... not having the actual response exposes us to possible deserialization errors Posting:

{
"server_id": "",
"shared_server": {
"library_section_ids": [
"movieid",
"showid"
],
"invited_email": "myfriends@email.com"
},
"sharing_settings": {
"allowSync": "0",
"allowCameraUpload": "0",
"allowChannels": "0",
"filterMovies": {},
"filterTelevision": {},
"filterMusic": {}
}
}

Get's a response of

<?xml version="1.0" encoding="UTF-8"?>
<MediaContainer friendlyName="myPlex" identifier="com.plexapp.plugins.myplex" machineIdentifier="myMachineID" size="1">
    <SharedServer id="myServerID" username="" email="" userID="" accessToken="" name="MyFriendlyName" acceptedAt="0" invitedAt="1709648402" allowSync="0" allowCameraUpload="0" allowChannels="0" allowTuners="0" allowSubtitleAdmin="0" owned="0">
        <Section id="movieid" key="1" title="Movies" type="movie" shared="1"/>
        <Section id="showid" key="2" title="TV Shows" type="show" shared="1"/>
    </SharedServer>
</MediaContainer>

Which is accompanied by the email supplied to get this image

Some of the errors: When sending to yourself

<?xml version="1.0" encoding="UTF-8"?>
<Response code="400" status="You cannot send an invitation to yourself."/>

When sending to some one you've already shared

<?xml version="1.0" encoding="UTF-8"?>
<Response code="400" status="You're already sharing this server with theirName Please edit your existing share."/>
kekolab commented 8 months ago

Fixed with c0afc20