|
Joined: Jun 2014
Posts: 52
Babel fish
|
OP
Babel fish
Joined: Jun 2014
Posts: 52 |
Off and on for the past few months I have been trying to figure out how to make a good song request system. Here is what I have found/planned so far: 1. As each user requests a song, it will be stored in a text file. (I forgot to add here, that it would be SUPER neat if I could somehow send these song requests straight from MIRC to my local webpage. Using AJAX I think I could intercept this data and make things work.) 2. Using my own local server I will set up a web page that will play these songs in a playlist (similar to nightbot). I have yet to study how to make a playlist with youtube links, but I am sure hoping it doesn't involve complicated code trying to find out if/when a song has finished. I should hope that there is a simple way to create a temporary playlist that automatically deletes a song once it has been played. Here is where I need help. So far, I have been stuck on how to use this google api http://gdata.youtube.com/feeds/api/videos/R0xoMhCT-7Ato determine if a youtube url is valid or not. I don't want anything fancy. I have tried using all sorts of scripts online, but they either A. assume that you put a valid link in, and obviously return valid info on it or B. are a complicated mess that are meant to just give json data on a url. All I need is a simple way to see if there is a 404 error, or a 200 "good to go" response. I should think this should be accomplished in less than 10 lines of code right? Thanks for any help, I would not be here if I were not at wit's end. Jon
Last edited by darthclide; 25/06/14 05:58 PM. Reason: wanted to make a point about using ajax
|
|
|
|
Joined: Jun 2014
Posts: 52
Babel fish
|
OP
Babel fish
Joined: Jun 2014
Posts: 52 |
I am still not sure how forums work when you "edit" a post (as in, does it "bump" it back up to the top), but I figured I would just send a reply with more details. As you have probably guessed, I have a little programming experience, but still don't understand some of these advanced methods such as sockets. I am a little worried from lack of a response. Meaning, even if all somebody did, was come in here and confirm something simple like this can be done, it would do wonders for my confidence. Even sending me to a tutorial on what I would need to check that validity of that gdata link. The silence makes me think this isn't as simple as I thought it was
Last edited by darthclide; 29/06/14 03:22 AM.
|
|
|
|
Joined: Jan 2004
Posts: 1,358
Hoopy frood
|
Hoopy frood
Joined: Jan 2004
Posts: 1,358 |
You can check out my sockets in this script: https://gist.github.com/memnochxx/5676bef5707a8019f0caIn general I define an alias to create a hash table and open a socket. The socket events use this hash table (as the same name as the socket) to get the data to be passed to the server. Then I define a signal to be called when the socket is done which then reads the header and data received. twitch.topic is probably a good starting point.
|
|
|
|
Joined: Dec 2013
Posts: 779
Hoopy frood
|
Hoopy frood
Joined: Dec 2013
Posts: 779 |
Nillens @ irc.twitch.tv Nillen @ irc.rizon.net
|
|
|
|
Joined: Jun 2014
Posts: 52
Babel fish
|
OP
Babel fish
Joined: Jun 2014
Posts: 52 |
based off your code this is what I have so far:
on @*:text:!song*:#:{
if ($2 != $null) {
song # $2-
}
}
alias song {
var %videoid = $gettok($2-,1,35)
%videoid = $gettok(%videoid ,2-,61)
var %chan = #$$1, %song = $2-
var %sockname = song. $+ $ticks
hfree -w %sockname | .hmake %sockname
hadd %sockname request /feeds/api/videos/ $+ videoid
if (%song != $null) {
msg # %videoid
hadd %sockname method GET
hadd %sockname signal song.get
}
sockopen -e %sockname gdata.youtube.com 443
}
on *:signal:song.get:{
var %err = $1, %sockname = $2, %header = $3, %data = $4
if (* 200 OK iswm $read(%header,n,1)) msg Good Status: $json(%data,status)
else msg Bad Could not get status.
hfree -w %sockname
if ($isfile(%header)) .remove %header
if ($isfile(%data)) .remove %data
}
Yet the code never gets to song.get I don't even know if I am doing this right. This socket stuff is way beyond me, and the tutorials people have mentioned don't help me personally for 2 reasons: 1. I am not creating this code for anyone else. As such, I don't care if it looks ugly. I just want it to get the job done. 2. I have yet to find a tutorial that explains in layman's terms what happens at every point of code. If what I want could be explained at every step in pseudo code, it would help me understand sockets much better.
|
|
|
|
Joined: Jan 2004
Posts: 1,358
Hoopy frood
|
Hoopy frood
Joined: Jan 2004
Posts: 1,358 |
Where are all the socket events?
|
|
|
|
Joined: Jun 2014
Posts: 52
Babel fish
|
OP
Babel fish
Joined: Jun 2014
Posts: 52 |
What do you mean? I thought copying your code and tweaking it would work? I took out your oauth and chan stuff because i was 90% sure it was twitch code that isn't needed for youtube.
|
|
|
|
Joined: Jan 2004
Posts: 1,358
Hoopy frood
|
Hoopy frood
Joined: Jan 2004
Posts: 1,358 |
It should, but I can't know where it's breaking without the full script - especially because you must have changed it. There's nothing inherently wrong with what you've posted here, assuming that status is a valid field in the json you receive.
|
|
|
|
Joined: Jun 2014
Posts: 52
Babel fish
|
OP
Babel fish
Joined: Jun 2014
Posts: 52 |
when you say "status is a valid field". What do you mean? From what I remember with json, it just returns a bunch of fields with their values. In this case, if the link is valid there would be fields like "title" "description" etc etc. I simply thought that there would be 404 error if the link was invalid, and a 200 if there was success. That is all I want for now (to check if link is valid). Here is the full script below. I don't know if I need the 3 aliases "download", "youtube", and "json" when the only thing I want is A. Is the youtube url valid? and B. Down the road, I want to return the video name. A. and B. should take far less lines of code right?
; Thanks to FiberOptics for this nifty snippet ;)
; Requires the $download snippet can be found here: http://sephiroth.bounceme.net/forum/viewtopic.php?t=104
; No need to change anything normally
; Simply paste it to remote and you will get an echo after someone pasted a youtube uri
; if you wanna use it for a bot change the post alias to return $true
;
; Update: 21.01.2012
; - added some errorchecking
; - changed Wildmatch
; - better parsing
; - added youtu.be-links
alias -l post { return $true }
on *:TEXT:!requestsong*:#: {
var %url = http://gdata.youtube.com/feeds/api/videos/$2
}
on @*:text:!song*:#:{
if ($2 != $null) {
song # $2-
}
}
on *:text:!request *youtube*v=*:*: {
var %xtwo = $gettok($1-,1,35)
%xtwo = $gettok(%xtwo,2-,61)
var %url = $wildtok($1-,*youtube.com/*v=*, 1, 32)
if ($youtube(%url)) {
tokenize 9 $ifmatch
; Author -> $1
; Duration -> $2
; Rating -> $3
; Date (last updated OR published) -> $4
; Preview Picture -> $5
; Title -> $6
$iif($post,msg,echo $color(info)) $iif($chan,$chan,$nick) YouTube: $6 (Rating: $3 $+ ) from: $1 Date: $4 Duration: $2 Preview: $5 %url
}
}
on *:text:!request *youtu.be*:*:{
var %url = $wildtok($1-,http://youtu.be/*, 1, 32)
if ($len(%url)) {
%url = /?v= $+ $gettok(%url,3,47)
if ($youtube(%url)) {
tokenize 9 $ifmatch
$iif($post,msg,echo $color(info)) $iif($chan,$chan,$nick) YouTube: $6 (Rating: $3 $+ ) from: $1 Date: $4 Duration: $2 Preview: $5 %url
}
}
}
alias song {
var %videoid = $gettok($2-,1,35)
%videoid = $gettok(%videoid ,2-,61)
var %chan = #$$1, %song = $2-
var %sockname = song. $+ $ticks
hfree -w %sockname | .hmake %sockname
hadd %sockname request /feeds/api/videos/ $+ videoid
if (%song != $null) {
msg # %videoid
hadd %sockname method GET
hadd %sockname signal song.get
}
sockopen -e %sockname gdata.youtube.com 443
}
on *:signal:song.get:{
var %err = $1, %sockname = $2, %header = $3, %data = $4
if (* 200 OK iswm $read(%header,n,1)) msg Good Status: $json(%data,status)
else msg Bad Could not get status.
hfree -w %sockname
if ($isfile(%header)) .remove %header
if ($isfile(%data)) .remove %data
}
alias -l urlencode return $regsubex($1-,/([^A-Z0-9])/gi,$+(%,$base($asc(\1),10,16)))
alias youtube {
; http://www.youtube.com/watch?v=B0fFDk2M0zE&feature=fvhl#cookie
; example: $youtube(...youtube.com/watch?v=vid)
var %x = $gettok($1-,1,35) , %o = $null, %r = $null, %y = 0
%x = $gettok(%x,2-,63)
%y = $numtok(%x,38)
while (%y) {
%o = $gettok(%x,%y,38)
if ($gettok(%o,1,61) == v) { %r = $gettok(%o,2,61) }
dec %y
}
if (!$len(%r)) { return $false }
else { %x = %r }
if ($download(tmpfile,GET,http://gdata.youtube.com/feeds/api/videos/ $+ %x ,2)) {
bread tmpfile 0 $lof(tmpfile) &bin
var %string = $b(&bin,<author>)
if ($regex(%string,/\<author\>\<name\>(.*)\<\/name\>/ig)) { var %author = $regml(1) }
var %string = $b(&bin,<yt:duration)
if ($regex(%string,/\<yt:duration seconds='([\d]+)'\/\>/ig)) { var %duration = $duration($regml(1),3) }
var %string = $b(&bin,<gd:rating)
if ($regex(%string,/average='([^']+)' max='([\d]+)'/ig)) { var %rating = $round($regml(1),3) }
var %string = $b(&bin,<title)
if ($regex(%string,/type='text'>([^<]+)/ig)) { var %title = $regml(1) }
var %string = $b(&bin,<updated>)
if ($regex(%string,/\<updated>([\d]{4})-([\d]{2})-([\d]{2})T([\d]{2}:[\d]{2})\:/ig)) { var %date = $regml(3) $+ . $+ $regml(2) $+ . $+ $regml(1) $regml(4) }
else {
var %string = $b(&bin,<published>)
if ($regex(%string,/\<published>([\d]{4})-([\d]{2})-([\d]{2})T([\d]{2}:[\d]{2})\:/ig)) { var %date = $regml(3) $+ . $+ $regml(2) $+ . $+ $regml(1) $regml(4) }
}
var %preview = http://i.ytimg.com/vi/ $+ %x $+ /0.jpg
if ($isfile(tmpfile)){!.remove tmpfile}
if (!$len(%author)) var %author = n/a
if (!$len(%duration)) var %duration = 00:00:00
if (!$len(%date)) var %date = n/a
if (!$len(%preview)) var %preview = n/a
if (!$len(%title)) var %title = n/a
if (!$len(%rating)) var %rating = n/a
%x = $t(%author,%duration,%rating,%date,%preview,%title)
}
else { var %x = $false }
if ($isfile(tmpfile)) { !.remove tmpfile }
return %x
}
alias -l t { var %x = $0,%o | while (%x) { %o = $ [ $+ [ %x ] ] $+ $chr(9) $+ %o | dec %x } | return %o }
alias -l b { return $bvar($1,$bfind($1,1,$2).text,$iif($version > 6.31,4000,800)).text }
alias download {
var %r = $(|,) return $false, %e = scon -r !echo $color(info) -a $!!download: Error -
if (!$isid) %e this snippet can only be called as an identifier. %r
if ($os isin 9598) %e this snippet requires Windows ME or higher. %r
if ($version < 6) %e this snippet requires mIRC version 6.0 or higher. %r
var %dir = $nofile($1), %file = $nopath($1), %method = $upper($2), %url = $3
if (!$gettok(%dir,2,58)) { %dir = $mircdir $+ %dir }
var %bit = $4, %headers = $iif($2 == get,$5,$6), %postdata = " $+ $5", %res
if (* !iswm %file) %e you must specify a file to save the data to. %r
if (%file != $mkfn(%file)) %e file %file contains illegal characters. %r
if (* !iswm %dir) %dir = $mircdir
elseif (!$isdir(%dir)) %e no such folder %dir %r
if (!$istok(get head post,$2,32)) %e method can only be GET, HEAD or POST. %r
;if (!$regex(%e,$3,/^\S+\.\S+\.\S+$/)) %e you didn't specify an url to download from. %r
if ($2 != head) {
if ($4 !isnum 1-3) %e bitmask should be a digit in range 1-3. %r
if ($2 == post) && (* !iswm $5) %e you didn't specify any post data. %r
if (%headers) && (!$regsub(%e,%headers,/(\S+?): (.+?)(?=\s?\n|$)/g,"\1" $chr(44) "\2",%headers)) {
%e bad header syntax. Correct -> Label: value seperated by $!!lf's %r
}
}
var %file = $+(",%dir,%file,"), %id = $+(@download,$ticks,$r(1111,9999),.vbs), %a = aline %id
if ((http://* !iswm $3) && (https://* !iswm $3)) { %url = http:// $+ $3 }
.comopen %id wscript.shell
if ($comerr) %e could not open Wscript.Shell. %r
write -c %file
window -h %id
%a on error resume next
%a sub quit $lf set http = nothing : set ado = nothing : wscript.quit $lf end sub
%a sub errmsg
%a set fso = createobject("scripting.filesystemobject")
%a set file = fso.createtextfile( %file ,true)
%a file.write("Err number: " & err.number & " = " & err.description) : file.close
%a set fso = nothing
%a quit
%a end sub
%a arr = array("winhttp.winhttprequest.5.1","winhttp.winhttprequest","msxml2.serverxmlhttp","microsoft.xmlhttp")
%a i = 0 $lf while i < 4 and not isobject(http) : set http = createobject(arr(i)) : i = i + 1 : wend
%a if not isobject(http) then errmsg
%a err.clear
%a http.open $+(",%method,") , $+(",%url,") ,false
%a http.setrequestheader "User-Agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)"
if (%headers) { tokenize 10 %headers | scon -r %a http.setrequestheader $* }
if (%method == post) {
%a http.setrequestheader "Content-Type","application/x-www-form-urlencoded"
%a http.send %postdata
}
else %a http.send
%a if err then errmsg
%a set ado = createobject("adodb.stream")
%a if not isobject(ado) then errmsg
%a ado.open
if (%bit != 2) {
%a ado.type = 2 : ado.charset = "ascii"
%a ado.writetext "HTTP/1.1 " & http.status & " " & http.statustext,1
%a ado.writetext http.getallresponseheaders,1 : ado.position = 0
}
if (%bit != 1) %a ado.type = 1 : ado.read : ado.write http.responsebody
%a ado.savetofile $iif($mid(%file,3,1) != :,$qt($mircdir $+ $remove(%file,")),%file) ,2 : ado.close : quit
savebuf %id $qt($mircdir $+ %id)
close -@ %id
.comclose %id $com(%id,run,1,bstr*,wscript.exe $qt($mircdir $+ %id),uint,0,bool,true)
.remove %id
; * This fixes one Line HTML Files with more than 4000 chars per line * (for example winamp shoutcast servers)
.fopen file %file
.fseek -w file Err number:* = *
var %pos = $fopen(file).pos
.fclose file
if ((%x < 0) || (%x > 10)) {
if (!%pos){
%res = $read(%file,t,1)
if (Err number:*=* iswm %res) || (!$file(%file)) %e $iif(%res,%res,no data could be retrieved) - %url %r
}
else {
return $true
}
:error
if ($com(%id)) .comclose %id
if ($isfile(%id)) .remove %id
if ($window(%id)) close -@ %id
return $false
}
alias json {
if ($isid) {
;name of the com interface declared so I don't have to type it over and over again :D
var %c = jsonidentifier,%x = 2,%str,%p,%v
;if the interface hasnt been open and initialized, do it.
if (!$com(%c)) {
.comopen %c MSScriptControl.ScriptControl
;add two javascript functions for getting json from urls and files
noop $com(%c,language,4,bstr,jscript) $com(%c,addcode,1,bstr,function httpjson(url) $({,0) y=new ActiveXObject("Microsoft.XMLHTTP");y.open("GET",encodeURI(url),false);y.send();return y.responseText; $(},0))
noop $com(%c,addcode,1,bstr,function filejson (file) $({,0) x = new ActiveXObject("Scripting.FileSystemObject"); txt1 = x.OpenTextFile(file,1); txt2 = txt1.ReadAll(); txt1.Close(); return txt2; $(},0))
;add function to securely evaluate json
noop $com(%c,addcode,1,bstr,function str2json (json) $({,0) return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(json.replace(/"(\\.|[^"\\])*"/g, ''))) && eval('(' + json + ')'); $(},0))
;add a cache for urls
noop $com(%c,addcode,1,bstr,urlcache = {})
}
if (!$timer(jsonclearcache)) { .timerjsonclearcache -o 0 300 jsonclearcache }
;get the list of parameters
while (%x <= $0) {
%p = $($+($,%x),2)
if (%p == $null) { noop }
elseif (%p isnum || $qt($noqt(%p)) == %p) { %str = $+(%str,[,%p,]) }
else { %str = $+(%str,[",%p,"]) }
inc %x
}
if ($prop == count) { %str = %str $+ .length }
;check to see if source is file
if ($isfile($1)) {
if ($com(%c,eval,1,bstr,$+(str2json,$chr(40),filejson,$chr(40),$qt($replace($1,\,\\,;,\u003b)),$chr(41),$chr(41),%str))) { return $com(%c).result }
}
;check to see if source is url
elseif (http://* iswm $1) {
;if url is in cache, used cached data
if ($com(%c,eval,1,bstr,$+(str2json,$chr(40),urlcache[,$replace($qt($1),;,\u003b),],$chr(41),%str))) { return $com(%c).result }
;otherwise, get data
elseif ($com(%c,executestatement,1,bstr,$+(urlcache[,$replace($qt($1),;,\u003b),]) = $+(httpjson,$chr(40),$qt($1),$chr(41)))) {
if ($com(%c,eval,1,bstr,$+(str2json,$chr(40),urlcache[,$replace($qt($1),;,\u003b),],$chr(41),%str))) { return $com(%c).result }
}
}
;get data from inputted json
elseif ($com(%c,eval,1,bstr,$+(x=,$replace($1,;,\u003b),;,x,%str,;))) { return $com(%c).result }
}
}
alias jsonclearcache { if ($com(jsonidentifier)) { noop $com(jsonidentifier,executestatement,1,bstr,urlcache = {}) } }
;-------------------;
;;;Basic Google Web Search Identifier;;;
;;;Only the first 8 results are retrieved;;;
;;;Syntax: $gws(<search params>,<result number>,<count|url|title|content>)
;;;Requires $json
alias gws {
;ensure a proper property (count, etc) is selected and result number is between 1 and 8
if (!$istok(count url title content,$3,32) && $2 !isnum 1-8) { return }
var %url = http://ajax.googleapis.com/ajax/services/search/web?q= $+ $1 $+ &v=1.0&safe=active&rsz=large
;check to see if results were found
;since results often come back with bolds, remove them
if ($json(%url,responseData,results,0)) { return $iif($3 == count,$json(%url,responseData,cursor,estimatedResultCount).http,$remove($json(%url,responseData,results,$calc($2 - 1),$3).http,<b>,</b>)) }
}
|
|
|
|
Joined: Jan 2004
Posts: 1,358
Hoopy frood
|
Hoopy frood
Joined: Jan 2004
Posts: 1,358 |
None of my socket events are in there. You have a youtube and download alias which are not related to the song alias and song.get signal in any way.
|
|
|
|
Joined: Jun 2014
Posts: 52
Babel fish
|
OP
Babel fish
Joined: Jun 2014
Posts: 52 |
ah I think I see what you are talking about: on *:sockopen:twitch.* on *:sockread:twitch.* on *:sockclose:twitch.*
Although I am not sure what to do about sockclose since you have it inside the "twitch.auth.request" which has nothing to do with youtube
|
|
|
|
Joined: Jan 2004
Posts: 1,358
Hoopy frood
|
Hoopy frood
Joined: Jan 2004
Posts: 1,358 |
Sockclose is called when the server closes the socket, which it should do automatically when it has finished sending data (if the connection: close header was specified).
I perform a sockclose myself in the twitch.auth.request because in that instance I'm acting as a server to receive the token request when the browser redirects to the redirect_uri, it's not necessary for you.
|
|
|
|
Joined: Jun 2014
Posts: 52
Babel fish
|
OP
Babel fish
Joined: Jun 2014
Posts: 52 |
Considering how long I am taking between replies, I am not expecting much, but I am hoping for some help on how to tweak the following to say "youtube link is valid" or "youtube link is not valid" on @*:text:!song*:#:{
if ($2 != $null) {
demo $2
}
}
alias demo {
%videoid = $1
%sockname = demo. $+ $ticks
hfree -w %sockname | hmake %sockname
hadd %sockname host gdata.youtube.com
hadd %sockname port 80
hadd %sockname request /feeds/api/videos/%videoid
sockopen -e %sockname $hget(%sockname,host) $hget(%sockname,port)
}
on *:sockopen:demo.*: {
var %<< = sockwrite -nt $sockname
%<< GET $hget($sockname,request) HTTP/1.0
%<< Host: $sock($sockname).addr
%<< $crlf
}
on *:sockread:demo.*: {
var %header, %content
if (!$hget($sockname,header.complete)) {
sockread %header
while (%header != $null) {
if (HTTP/* 2?? * iswm %header) { hadd $sockname following $true }
elseif (HTTP/* 4?? * iswm %header) {
}
;echo -ag %header
sockread %header
}
if ($sockbr) hadd $sockname header.complete $true
}
if ($hget($sockname,header.complete)) {
while ($sockbr) {
sockread -f %content
;if (%content != $null) echo -ag %content
}
}
}
on *:sockclose:demo.*:{
if ($hget($sockname,following)) { var %msg = Following }
else { var %msg = Not following }
if ($hget($sockname,chan)) { msg $v1 %msg }
else { echo -ag %msg }
hfree $sockname
}
|
|
|
|
Joined: Jun 2014
Posts: 52
Babel fish
|
OP
Babel fish
Joined: Jun 2014
Posts: 52 |
*Update* I finally tweaked sephiroth's code to tell me if a youtube link is invalid or not. I really don't like hard-coding things to work and in this case it simply sees if "n/a" exists in the title. We will see if a youtube video comes along and somehow messes up on that piece of code, but it will suffice for now.
What I would like help on now is the following: 1. For the time being, if I am going to host this songrequest page on localhost, what language should I use? I was leaning towards a page with ajax since last time I used it on web development it was a great way to update the page on the fly without needing to refresh the whole page. 2. If I use ajax or something similar, can someone point me towards how I would use sockets to send the videoid to the page?
I should be able to get help from my past boss on how to make the playlist, but if I can at least get help on sending the id to my localhost page then that would be great.
|
|
|
|
|