Having issues with PUT request to follow a channel

Hello,
I’m trying to create a follow button, and I’m having some issues getting my PUT request to succeed. I’m pretty sure that I’m incorrectly setting headers, but I haven’t been able to find where I’m going wrong. I’m sending an asynchronous request, and I’m pretty sure I’m handling that properly, but my code fails upon checking for readystate === 4 && status === 200. I also wanted to note that I included information about Content-Length based on this post: Link to Post. Hopefully someone can point out what I’m doing wrong? I really appreciate it.

P.S. I have tried to send this request with the sdk, but ran into issues. I didn’t want to make this post too long. If that is the simplest way of doing this, I can talk about issues I’m having with that method in a response to this original post.

Here’s my follow function:

function follow(channel)
{
    var success = function()
    {
        // Change color of button to green and change 'Follow' to 'Followed'
        document.getElementById("follow-button").innerHTML = "Followed";
        document.getElementById("follow-button").className = "btn btn-success btn-lg btn-block";
        document.getElementById("follow-button").removeAttribute("onclick");
    }
    var failure = function(step)
    {
        // Popup saying 'Something broke, make sure you're logged into twitch.'
        //var token = Twitch.getToken();
        window.alert("Something went wrong at step: " + step);
    }
    
    Twitch.getStatus(function(error, status)
    {
        if(error) return failure("1");
        if(!status.authenticated) return failure("-1");
        
        Twitch.api({method: 'user'}, function(error, user)
        {
            if(error) return failure("2");
            var xmlHttp = new XMLHttpRequest();
            var url = "https://api.twitch.tv/kraken/users/" + user.name + "/follows/channels/" + channel;
            xmlHttp.onreadystatechange = function()
            {
                if (xmlHttp.readyState === 4 && xmlHttp.status === 200) 
                {
                    success();
                }
                else 
                {
                    failure("3"); // This is the step that my code fails at currently.
                }
            };
            xmlHttp.open('PUT', url, true);
            xmlHttp.setRequestHeader("Content-Type", "application/json");
            xmlHttp.setRequestHeader("Accept", "application/vnd.twitchtv.v3+json");
            xmlHttp.setRequestHeader("Authorization", "OAuth " + Twitch.getToken());
            xmlHttp.setRequestHeader("Content-Length", "0");
            xmlHttp.send();
        });
    });
}

I don’t think I’m qualified to answer this, but would this work?

        {
            if (xmlHttp.readyState==4) 
            {
                var check=xmlHttp.status;
  			alert(check);
  			if (check.toString()=="200")
  			{
  				success();
  			}
            }
            else 
            {
                failure("3"); // This is the step that my code fails at currently.
            }
        };

Ok so actually thanks for that, readyState eventually hits 4, so when I grab the status I actually get a 401 error, which I think means that I’ve only sent a GET request? I’m thinking that the request is just checking if the user is following that channel, and is returning null or something since the user is not.

    Twitch.api({method: 'user'}, function(error, user)
    {
        if(error) return failure("2");
        var xmlHttp = new XMLHttpRequest();
        var url = "https://api.twitch.tv/kraken/users/" + user.name + "/follows/channels/" + channel;
        xmlHttp.open('PUT', url, true);
  	xmlHttp.onreadystatechange = function()
        {
            if (xmlHttp.readyState==4) 
            {
                var check=xmlHttp.status;
  			alert(check);
  			if (check.toString()=="200")
  			{
  				success();
  			}
            }
            else 
            {
                failure("3"); // This is the step that my code fails at currently.
            }
        };
        xmlHttp.setRequestHeader("Content-Type", "application/json");
        xmlHttp.setRequestHeader("Accept", "application/vnd.twitchtv.v3+json");
        xmlHttp.setRequestHeader("Authorization", "OAuth " + Twitch.getToken());
        xmlHttp.setRequestHeader("Content-Length", "0");
        xmlHttp.send();
    });
});

Putting .open before onreadystatechange still doesn’t fix the issue (I think that’s the only other thing I needed to try changing from your code?

I saw someplace that

The correct order of calls is:

new XMLHttpRequest
xhr.open()
xhr.onreadystatechange = …
xhr.send()

Ok. I did change that in my code and left it, because I think that actually is the proper way of doing it. I’m pretty sure it’s something to do with my headers.

Apparently a 401 error has to do with me being unauthorized, but that confuses me because I check if I’m authenticated with my code before calling Twitch.api, and I’ve run code to print out the results of Twitch.getToken() to check if I’m getting a valid token.

I have seen some posts about people having issues with the OAuth in the headers(or the other way around), perhaps try dropping it in the URL?

var url = “https://api.twitch.tv/kraken/users/” + user.name + “/follows/channels/” + channel"?oauth_token=["+ Twitch.getToken() + “]”;

See if that works.

This is how you’d do it with the JS SDK. Just make sure you’re using the version on github and not the CDN hosted one.

Twitch.api({
    method: 'users/' + user.name + '/follows/channels/' + channel,
    verb: 'PUT'
}, function (error, data) {
    // ...
});
2 Likes

Hah! See…

3ventic with a good solution.

1 Like

This is a stupid question but this is the CDN version right?

<script src="https://ttv-api.s3.amazonaws.com/twitch.min.js"></script>

I’ve downloaded the Twitch SDK straight off of github from the repository, but using this downloaded version of twitch.min.js with the same code, I actually am logged out of my authenticated session with twitch and have to re-connect/re-authenticate on my webpage.

Looking at the Makefile, it seems that everything is already built. I don’t have to make the project myself do I? I do have docco & UglifyJS installed on my computer but like I said, it looks like everything’s good to go.

Here’s my code just for reference:

function follow(channel)
{
    var success = function()
    {
        // Change color of button to green and change 'Follow' to 'Followed'
        document.getElementById("follow-button").innerHTML = "Followed";
        document.getElementById("follow-button").className = "btn btn-success btn-lg btn-block";
        document.getElementById("follow-button").removeAttribute("onclick");
    }
    var failure = function(step)
    {
        // Popup saying 'Something broke, make sure you're logged into twitch.'
        var token = Twitch.getToken();
        window.alert("Something went wrong at step: " + token);
    }
    
    Twitch.getStatus(function(error, status)
    {
        if(error) return failure("1");
        if(!status.authenticated) return failure("-1");
        
        Twitch.api({method: 'user'}, function(error, user)
        {
            if(error) return failure("2");
            
            Twitch.api({method: '/users/' + user.name + '/follows/channels/' + channel, verb: 'PUT'}, function(error, response)
            {
                if(error) return failure(user.name);
                success();
            });
        });
    });
}

Oh. My. God. Guys.

I am so sorry for waisting your time. It turns out that I didn’t include ‘user_follows_edit’ in my scope. Seems to be working now.

I really appreciate the help and the time.

I’m glad it’s all sorted out!

Thanks <3

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.