1

我目前正在为我的 Twitch 机器人开发一个新的正常运行时间命令,但我遇到了套接字问题。我正在尝试使用此页面http://api.twitch.tv/api/channels/duilio1337检查流媒体是否在线。它有时可以正常工作,但有时它会读取页眉而不是页面。似乎是随机的。

alias uptimecheck {
  echo -a CHECKING CHANNEL $1 STATUS
  %uptimeurl = /api/channels/ $+ $1
  %uptimecheckchan = $1
  sockopen wuptime api.twitch.tv 80
}

on *:sockopen:wuptime: {
  sockwrite -n $sockname GET %uptimeurl HTTP/1.0
  sockwrite -n $sockname User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
  sockwrite -n $sockname Host: api.twitch.tv
  sockwrite -n $sockname Accept-Language: en-us
  sockwrite -n $sockname Accept: */*
  sockwrite -n $sockname
}

on *:sockread:wuptime: {
  if ($sockerr) {
    echo -a UPTIME Connection Error.
    halt
  }
  else {
    sockread -f %uptimeliverail
    if ($sockbr == 0) return
    ;echo -a %uptimeliverail
  }
}

on *:sockclose:wuptime: {
  var %TEMPliverail $mid(%uptimeliverail, $calc($pos(%uptimeliverail, "twitch_liverail_id") + 21), 4)
  if (%TEMPliverail == null) {
    set %uptimelive. $+ %uptimecheckchan 0
  }
  else if (%TEMPliverail isnum) {
    set %uptimelive. $+ %uptimecheckchan 1
  }
}
4

2 回答 2

0

http://api.twitch.tv/api/channels/duilio1337的内容只是:

{"display_name":"duilio1337","game":null,"status":"Test","fight_ad_block":false,"_id":47890122,"name":"duilio1337","partner":false,"comscore_id":null,"comscore_c6":null,"twitch_liverail_id":null,"hide_ads_for_subscribers":false,"liverail_id":null,"ppv":false,"video_banner":null,"steam_id":null,"broadcaster_software":"unknown_rtmp","prerolls":true,"postrolls":true,"product_path":""}

它不是 HTML 页面,所以你的意思是:它读取页面标题而不是页面。?

也许你可以更好地解释你的问题。

无论如何...我认为就您的sockopen活动而言,发送 GET 和 Host 标头就足够了:

on *:sockopen:wuptime: {
  sockwrite -nt $sockname GET %uptimeurl HTTP/1.1
  sockwrite -nt $sockname Host: api.twitch.tv
  sockwrite $sockname $crlf                   
}
  • 在 HTTP/1.0 中,Host不需要,但不会受到伤害。在 HTTP/1.1 中是必需的。
  • 建议该-t参数避免&被视为二进制变量。
  • sockwrite $sockname $crlf是完成 HTTP 请求的更明确的方式,并且与您的sockwrite -n $sockname(因为-n添加了)等效(IIRC $crlf)。

此外,您的sockread活动通常应如下所示:

on *:sockread:wuptime: {
  if ($sockerr) {
    ;error msg code here
    return
  }

  var %data
  sockread %data

  ;your code here

  unset %data
}
  • 避免halt,该命令用于立即停止任何进一步的处理。大多数情况下使用比较合适return
  • 避免不必要if-else的条件。

需要注意的是,每次服务器回复一行时,sockread都会启动该事件。

于 2014-12-31T21:48:09.150 回答
0

服务器最有可能返回

Vary: Accept Encoding

在响应头中。尝试Accept */*

sockwrite -n $sockname Accept: gzip

看看会发生什么。它很可能会返回压缩的二进制数据(而不是超时,或者什么都不返回)。问题是,mIRC 不能解压这个并且不支持 gzip 解码。昨晚我遇到了同样的问题,这就是我为使用 mIRC 套接字并需要获取 gzip 内容的任何人解决它的方法。

首先确保像我上面那样更改标题.. 到Accept: gzip

其次,从http://www.7-zip.org/a/7za920.zip获取 7za(Windows 控制台的 7-zip)的副本。解压 7za 并将其放在c:\program files (x86)\mIRC\文件夹中,或 mirc.exe 所在的任何位置。

我已经修改了 OP 的*on:sockread:块来获取和提取下面的 gzip 内容:

on *:sockread:wuptime:{
  var %bare $rand(423539,999999)
  var %gz 1

  :play
  var %dg
  sockread %dg

  :wile
  if ( %gz = 2 ) {
    sockread -f &gzd
  }
  if ($sockerr) {
    return 
  }
  if ( %gz = 2 ) {
    while ($sockbr) {
      bwrite %bare -1 -1 &gzd
      sockread -f &gzd
    }
  }
  if ($sockbr == 0) {
    sockclose $sockname
    echo -at closed
    run -h 7za.exe e %bare
    .timer 1 2 wuptimeparse %bare
    return
  }
  if ( %dg = $null) {
    var %gz 2
    goto wile
  }

  goto play
}

这可能很粗糙,但是bwrite一旦标头完成返回,它就会开始生成一个随机文件,一旦$sockbr为空,它就会在压缩的二进制数据上运行 7zip。下面的别名将在几秒钟内被调用(7zip 发挥其魔力的时间.. 你可能会以一种更优雅的方式做到这一点,我确信)吐出你正在寻找的明文 JSON。请注意,如果您的示例中的 JSON 很大(4000 多个字符),您需要将其作为 binvar 读取,bread因为字符串太大而无法放入变量中。

alias wuptimeparse {
  var %file $1
  var %bare $read(%file $+ ~,1)
  echo %bare
  ;do something with %bare
  .timer 1 1 remove %file
  .timer 1 1 remove %file $+ ~
}
于 2015-10-30T04:29:07.213 回答