Get reward redeems with IRC Chat?

It was pointed out to me today, that custom reward redeems do NOT come over in the IRC chat at all. ugh.

Thought I could then use this API call set to pull down things every so often.

https://api.twitch.tv/helix/channel_points/custom_rewards/redemptions?

I can get the list of ID’s for rewards I have made via the TWICH website interface.

But trying to get it via

https://api.twitch.tv/helix/channel_points/custom_rewards/redemptions?broadcaster_id=225160664&reward_id=a7fe5de6-9d3b-46a9-9762-9eaa70175fdb&status=UNFULFILLED

returns

{
“error”: “Forbidden”,
“status”: 403,
“message”: “The ID in the Client-Id header must match the client ID used to create the custom reward, or the broadcaster doesn’t have partner or affiliate status.”
}

I assume this is because these were made via the Twitch interface, not my program making them?

If so, how can I know about these getting redeemed?

Correct

EventSub and PubSub will both send redemptions as they occur in real time regardless of the ClientID security block.

or alternatively delete the reward from the dashboard then use the API to create it.

Once it’s created vai the API and your ClientID, you can then do whatever you want to it via the dashboard.

Ugh, was hoping to stay away from websockets. Since 90% of what im trying to do works with just the IRC protocol.

Not wanting to reinvent everything twitch has to offer… just trying to get myself a simple helper program… ugh …

So i guess now i gotta spend more time to wrap more calls… and make a whole UI… CRUD the redeems now… ugh…

Twitch API is gonna give me some twitches soon maybe… Good thing I am on meds.

Well unfortunately the only rewards sent via IRC at the ones that have a user prompt for the user to put a message with their redeem.

So you need to change the owner of the redemption or to use EventSub.

Ok. Got websockets working finally after doinking a few hours.

I take it now, you can only subscribe to one event at a time?

So if I want to monitor 2 or more things, I need to create 2 or more websockets, and register one “type” per websocket?

Also can I get chat text with this? Looking at EventSub Subscription Types | Twitch Developers

This is A no? Basically can this be used inplace of IRC protocol? I couldn’t see a message to register to.

Way to many moving parts to this whole beast… Websockets, IRC, HTTP POST, blah…

Can’t write to the websocket to register the event… gotta use the HTTP POST …

Just all seems willy nilly odd to me…

EventSub has no bulk create. But you can create multiple topics where transport

No you do not need 1 websocket per topic, you can subscribe to as many as you can fit within the posted limits.

This example - EventSub WebSockets with Implicit Auth Example creates 1 websocket and adds 6 subscriptions to it.

“Regular chat” messages are not provided as an eventsub topic.
But things like cheer and resubscriptions will provide the message text attached to that event.

So POST to the subscribe link X times? Ans reuse the Session ID each time?

As it looks like you can’t do single POST to subscribe scopes within the “type” field

Yes

The session ID rerepresents the socket you want to recieve data on.

What do you mean “scopes”?

Not sure what you are doing here

You have to pass a Type… so in my case I want to monitor channel.update and channel.channel_points_custom_reward.add

I was originally thinking you could do

{
  "type": "user.update channel.channel_points_custom_reward.add",
  "version": "1",
  "condition": {
    "broadcaster_user_id": "1234"
  },
  "transport": {
    "method": "websocket",
    "sessionid": "123abcxyz"
  }
}

Two types in one call.

I take it probably not this way as if one of the types failed for whatever reason, that would complicated the response on what failed and what passsed.

But it looks like just two to HTTP POST’s … one for each TYPE I want to monitor and re-use the sessionID for each POST.

It’s one type per call

So you subscribe to the Two topics specified you need to make two seperate requests.

Yup I understand this now. Thanks for the help.

1 Like

The documentation has an error I think.

Condition object is not defined well?

A JSON object that contains the parameter values that are specific to the specified subscription type. For the object’s required and optional fields, see the subscription type’s documentation.

No link to what they me to read?

Some places I see say it contains user_id and others broadcaster_user_id

Only way I knew kinda what to pass in the condition field was by the CURL example.

Which I still had to modify to broadcaster_user_id

That is the condition

The conditions requried will depend on the topic.

Refer to EventSub Subscription Types | Twitch Developers for the conditions for a given topic

And this link is linked in the type row of the screenshotted table.

Not sure why i am struggling with Twitch Docs…

I’ve been using eBay SOAP and REST API’s for 10+ years, and those are 1000x bigger/more complex and don’t seem to struggle as bad reading them.

Plus other services I deal with for my day I don’t seem to have this big of issue.

Just when I read these pages, the layout just doesn’t flow / jive with me at all.

export class PubSub {

  /**
   * Heartbeat Interval Handle
   *
   * @returns Number
   */
  heartbeatHandle = null;

  /**
   * WebSocket
   *
   * @returns Object
   */
  socket = null;

  /**
   * Config
   *
   * @returns Object
   */
  config = {};

  /**
   * Subscription handlers
   *
   * @returns Object
   */
  static subHandlers = {};

  /**
   * Channel point reward handlers
   *
   * @returns Object
   */
  static rewardHandlers = {};

  constructor (config) {
    this.config = config;
  };

  /**
   * Add a channel point reward handler
   *
   * @param {String}
   *          caller
   * @param {Function}
   *          handler
   * @returns PubSub
   */
  addRewardHandler (caller, handler) {
    PubSub.rewardHandlers[caller] = handler;
    return this;
  };

  /**
   * Remove a channel point reward handler
   *
   * @param {String}
   *          caller
   * @returns PubSub
   */
  removeRewardHandler (caller) {
    delete PubSub.rewardHandlers[caller];
    return this;
  };

  /**
   * Add a subscription handler
   *
   * @param {String}
   *          caller
   * @param {Function}
   *          handler
   * @returns PubSub
   */
  addSubHandler (caller, handler) {
    PubSub.subHandlers[caller] = handler;
    return this;
  };

  /**
   * Remove a subscription handler
   *
   * @param {String}
   *          caller
   * @param {Function}
   *          handler
   * @returns PubSub
   */
  removeSubHandler (caller) {
    delete PubSub.subHandlers[caller];
    return this;
  };

  /**
   * Connect to WebSocket
   *
   * @return Void
   */
  setupListener () {
    if (this.socket && this.socket.readyState != WebSocket.CLOSED) { return; }
    this.socket = new WebSocket('wss://pubsub-edge.twitch.tv');
    this.socket.onopen = event => {
      console.info('PubSub WebSocket connected.');
      this.heartbeatHandle = setInterval(() => {
        this.socket.send(JSON.stringify({
          type : 'PING'
        }));
      }, 6e4);
      this.socket.send(JSON.stringify({
        type : 'LISTEN',
        nonce : (() => {
          var text = '', possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
          for (var i = 0; i < 15; i++) {
            text += possible.charAt(Math.floor(Math.random() * possible.length));
          }
          return text;
        })(),
        data : {
          topics : [
            'channel-points-channel-v1.' + this.config.broadcaster,
            'channel-subscribe-events-v1.' + this.config.broadcaster
          ],
          auth_token : this.config.psOauth
        }
      }));
    };
    this.socket.onclose = event => {
      console.info('PubSub WebSocket closed.');
      clearInterval(this.heartbeatHandle);
      setTimeout(() => (console.info('PubSub WebSocket reconnecting...'), this.setupListener()), 3e3);
    };
    this.socket.onerror = console.error;
    this.socket.onmessage = event => {
      const eventData = JSON.parse(event.data);
      if (eventData.type == 'MESSAGE') {
        if (eventData.data.topic === 'channel-points-channel-v1.' + this.config.broadcaster) {
          const message = JSON.parse(eventData.data.message).data.redemption;
          for (var [caller, handler] of Object.entries(PubSub.rewardHandlers)) {
            handler(message.user.display_name, message.reward, message.user_input);
          }
        }
        if (eventData.data.topic === 'channel-subscribe-events-v1.' + this.config.broadcaster) {
          const message = JSON.parse(eventData.data.message);
          for (var [caller, handler] of Object.entries(PubSub.subHandlers)) {
            handler(message.display_name, message);
          }
        }
      }
    };
  };

  /**
   * Disconnect from websocket
   *
   * @returns Void
   */
  disconnectListener () {
    if (!this.socket || this.socket.readyState == WebSocket.CLOSED) { return; }
    this.socket.close();
  };
};

Here a JS class for pubsub that listens to channel point reward redemption and subscriptions.
Try it out.

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