xboxapi / Python-Wrapper

Python wrapper for https://xapi.us
MIT License
39 stars 16 forks source link

Client API version 2 #12

Closed 0verbyte closed 7 years ago

0verbyte commented 7 years ago

The current implementation is very manual as far as method definitions go. Version 2 should be written in a more OOP approach, in addition the current implementation should still be maintained for backwards compatibility. Perhaps a flag to the xboxapi constructor to trigger the new schema? Some ideas:

jebby commented 7 years ago

I just started python a couple days ago but looking at the source code, I saw something that I would like to see implemented (Given a little time, I could possibly help in implementing this):

So if you don't know somebody's gamertag, instead of doing this:

Xuid = api.get_xuid_by_gamertag(<Gamertag_Goes_Here>)

Profile = api.get_user_profile(Xuid)
print Profile

You could both skip a line (Retrieving theand make the method easier to use by adding a "Mode" parameter:

Profile = api.get_user_profile(Mode="Gamertag", <Gamertag_Goes_Here>)
print Profile

The way I was thinking this could be accomplished is to call the method "get_gamertag_by_xuid()" within the main when any function is called and has mode set to "Gamertag", so that it would convert the xuid to a gamertag, then passing it as a parameter to the original method. This would eliminate the hassle of needing to convert an xuid any time you have someone's Gamertag but not their xuid.

If I didn't explain clearly enough, think of the "Mode" parameter as combining the method you are using with get_gamertag_by_xuid() into one "Smart command"

0verbyte commented 7 years ago

Thank you for your feedback.

I think a lot of what you're describing here will be addressed with version 2, which I plan to start working in the coming days. If you'd like you can test it for me when it's in beta stage?

jebby commented 7 years ago

I will most definitely test the beta stages. I started working on a method that changes the "mode" that I was speaking of. I only got into Python about 5 or so days ago, so I don't know if this is the best way to do this but it at least gives something to call to:

def Mode(self, mode):
        self.mode = mode

#Just setting the possible parameters that can tell the method to set the mode
        GamertagModeNames = ["Gamertag", "gamertag", "G", "g"]
        XuidModeNames = ["Xuid", "xuid", "X", "x"]

        if self.mode in GamertagModeNames:
            self.mode = "Gamertag"
        elif self.mode in XuidModeNames:
            self.mode = "Xuid"
        else:
            return
        return self.mode

I was thinking maybe call to that method and use an if-else to check if it's equal to "Gamertag" or "Xuid" and add the corresponding code in it's block

jebby commented 7 years ago

Also, this one may be more of a hassle, but it would also be awesome if a couple of methods were added that took a list that was loaded with for example get_user_presence()

instead of printing out a list that you can iterate through, I feel that it would be more convienient to have duplicates of the method that are parsed differently so that I could possibly say

get_user_presence_OnlineStatus() - Could set a variable to "Online" or "Offline" instead of having to iterate through the list to find the tag for showing online status or get_user_presence_PlayingGame() - would do the same, but set a variable to the game the player is currently playing

I hope what I'm saying is making sense. I feel that this could make everything more user friendly instead of parsing strings on your own

jebby commented 7 years ago

I've made two methods that I added to the source and it allows me to pass a gamertag.(To clarify, I mean I added this code to my source. I provided the code I used below so you can copy paste into your source and see if you think we can implement this?)

What I added to the source code:

    def UserOnline(self, gamertag):
        gamertag = gamertag
        Xuid = self.get_xuid_by_gamertag(gamertag)
        Profile = self.get_user_presence(Xuid)
        Profile = Profile['state']

        return Profile
0verbyte commented 7 years ago

I think this is an interesting start. I had a different approach actually to how version 2 of the api will be.

I will push up a branch with the changes.

jebby commented 7 years ago

Alright, I'll be looking out for the v2 beta so I can test it out for you.

0verbyte commented 7 years ago

Sorry for the delay. I've started working on version 2 this weekend. If you would like you can test this, although it is not feature rich yet. The design is very similar to the Ruby gem of the xboxapi.

jebby commented 7 years ago

Yes, I'm interested in testing for you. Have you pushed it yet? Or are you planning to push it in the upcoming days?

jebby commented 7 years ago

Nevermind, I found it. Everything seems to work the way I expected it to. But what is the point of the "User" class? I understand HOW it works, but how does v2 benefit from it? Can the "User" class do something v1 couldn't do?

In the rate-limit, on "refresh" is that time in seconds?

What does it mean by "pre-fetch"?

I would suggest being able to manually set the "REQUEST_TIMEOUT" by putting "REQUEST_TIMEOUT=5" in the "init" function in the "Client" class. And then change any reference of "REQUEST_TIMEOUT" to "self.REQUEST_TIMEOUT" so that you can change the timeout in ANY script and not have to edit it from the source.

Also, If I may request something. Is it possible to make it so you can set your local language? For example on the XboxApi documentation it shows me how to set it to "de-DE" Could you make it so you can put what you would like? Such as ("en-US", "jp-JP", "de-DE") and so on?

Do you plan to add something similar to the functions that I had posted above?

Sorry for the wall of text... Just thought I should get all my questions out at one time.

0verbyte commented 7 years ago

I've made additional improvements.

I've added support for language and also the ability to use pagination with continuationToken. Pagination will only be trigger when the X-Continuation-Token is present in the api call response headers, when the response header exists all subsequent requests to the same api endpoint will be paged data.

Works like this:

client = Client(api_key="<token>")
gamer = client.gamer("voidpirate")
screenshots_firstpage = gamer.get('screenshots') # call will trigger the continuation token
screenshots_secondpage = gamer.get('screenshots') # will return second set of screenshots

# This call will return the state back to normal and continuation token will be cleared
gamer.get('activity-feed')

You can also see how the flow works now with the example above. I have 3 things I want to complete before merging to master.

  1. Add support for send messages and posting activity, along with any remaining API calls
  2. Unit tests
  3. Update README

Thanks for the feedback on the library btw, it's greatly appreciated 👍

0verbyte commented 7 years ago

.. and to answer your questions previously.

what is the point of the "User" class? I understand HOW it works, but how does v2 benefit from it? Can the "User" class do something v1 couldn't do?

It is more organized now and allows you to pass a gamertag and do a lookup for xuid behind the scenes, although you can just pass the xuid to prevent additional api calls and the lookup will be ignored.

# Useful if you know the xuid before hand
client.gamer(xuid=<xuid>)

In the rate-limit, on "refresh" is that time in seconds?

Do you mean the X-RateLimit-Reset? If so, yes this value is in seconds until your api calls are reset. Otherwise I don't know what the "refresh" is you're referring to.

I would suggest being able to manually set the "REQUEST_TIMEOUT" by putting "REQUEST_TIMEOUT=5" in the "init" function in the "Client" class. And then change any reference of "REQUEST_TIMEOUT" to "self.REQUEST_TIMEOUT" so that you can change the timeout in ANY script and not have to edit it from the source.

Yep, you can pass time out through the constructor like Client(timeout=<seconds>) (defaults to 3 seconds).

Also, If I may request something. Is it possible to make it so you can set your local language? For example on the XboxApi documentation it shows me how to set it to "de-DE" Could you make it so you can put what you would like? Such as ("en-US", "jp-JP", "de-DE") and so on?

Yep, you can pass your language of choice in the constructor Client(lang=<lang>) (defaults to english)

0verbyte commented 7 years ago

I've merged this with master