AutoHotkey Community

It is currently May 27th, 2012, 1:22 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 137 posts ]  Go to page Previous  1 ... 4, 5, 6, 7, 8, 9, 10  Next
Author Message
 Post subject:
PostPosted: March 26th, 2011, 6:36 pm 
Offline

Joined: March 7th, 2011, 2:59 am
Posts: 151
flashkid wrote:
It's me again. I have rewritten my functions to be a complete "Youtube library".
Have a look: YTLib.ahk
Example #1: Download a file with a given quality
Example #2: Download all possible qualities with correct file extensions

There is also a documentation available: YTLib Documentation


Clicking on Examples #1 and #2 brings up only blank pages? :arrow: :?:


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 26th, 2011, 6:44 pm 
Offline

Joined: August 25th, 2007, 9:25 pm
Posts: 110
Sorry, corrected the links


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 26th, 2011, 7:22 pm 
Offline

Joined: March 7th, 2011, 2:59 am
Posts: 151
For convenience sake, is it possible to put all flashkid's code in one page so that a newbie can copy & paste it into an .ahk file to click and download (similar to garry's script on page 1 or Christi's)? :lol: :idea:


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 27th, 2011, 7:57 pm 
Offline

Joined: April 19th, 2005, 10:26 am
Posts: 2250
Location: switzerland
MODIFIED=20110328
tried to make a GUI around flashkid's script
( again to much goto's ... grrr )

EDIT:
contains a progressbar
script must be corrected again by flashkid :) , contains a second httpquery
- and can just start once

needs:
httpQuery.ahk ;-- http://www.autohotkey.com/forum/viewtopic.php?t=33506
YTLib.ahk ;-- http://www.autohotkey.net/~flashkid/You ... /YTLib.ahk

Code:
MODIFIED=20110328
;--- example GUI to flashkid's script youtube -----------------------------------------
;--- works immediatelly when you click start button ----
;--- a test script, must be corrected by flashkid :) ---
;--- ( contains another httpquery inside )

#Include httpQuery.ahk    ;-- http://www.autohotkey.com/forum/viewtopic.php?t=33506
#Include YTLib.ahk        ;-- http://www.autohotkey.net/~flashkid/Youtube-Lib/YTLib.ahk
                          ;-- http://www.autohotkey.net/~flashkid/Youtube-Lib/YTLib.html

#NoEnv
SendMode Input
SetWorkingDir %A_ScriptDir%
RECXX        =c:\_A_INPUT              ;<<< record here
 IfNotExist, %RECXX%
     FileCreateDir, %RECXX%

;------- for test ------------------------------------------
c1=http://www.youtube.com/watch?v=nKKBmnIfQxg    ; portugal
;c1=http://www.youtube.com/watch?v=siJLeHAnZIk    ; fmt=37 1080HD Widescreen contains chinese characters u300a etc
;c1=http://www.youtube.com/v/nKKBmnIfQxg&autoplay=1
;c1=http://www.youtube.com/watch?v=RVLJw-YL7y0    ; china

Gui,2: +AlwaysOnTop
Gui,2:Font, CDefault , Fixedsys
Gui,2:Add,Edit,x10 y2 w360 h20 vURL,
;Gui,2:add,button, hidden default gA1,ok
Gui,2:add,button,x400 y3 h20 w80 gA1,< START
Gui,2:add,button, x650 y3 h20 w100  gFolder1,FOLDER
Gui,2:Add,Edit, x10 y35  w750 h20 vTitle1 readonly ,
Gui,2:Add,Text,  x10    y65                     ,PROGRESS
Gui,2:Add,Progress,    x150   y65    h20  w480   vPRBAR cFF7200 -smooth

Gui,2:Show,x10 y10 h125 w800,Youtube Adress  [start and then select quality to download]
GuiControl,2:,URL,%c1%
Gui,2:Font, CDefault ,Arial
Return
;-----------------------------------------------------------------
2GuiClose:
ExitApp

Folder1:
Gui,2:submit,nohide
run,%recxx%
return
;-----------------------------------------------------------------

A1:
gui,2:submit,nohide
;msgbox, 262208,MSGBOX,%url%


;if url not contains http://www.youtube.com/watch?v=
if url contains watch?v=
  goto,start2

stringmid,URL1aa,url,1,25
if URL1aa=http://www.youtube.com/v/
   {
   stringright,STRRR,url,11
   url=http://www.youtube.com/watch?v=%STRRR%
   goto,start2
   }

   {
   GuiControl,2:,Title1,Youtube URL is missing
   return
   }
;--------------------------------------------
start2:
ytSource  := httpQuery(url)
title     := YTGetTitle(ytSource)
qualities := YTGetQualities(ytSource)
;extension := YTGetExtension(fmt)


I=0
X1=10
Y1=90
loop,parse,qualities,`|
   {
   I++
   if I=1
   x1:=(x1)
   else
   x1:=(x1+135)
   asf=
   qualities=
   stringmid,qualities,A_Loopfield,1,2
   stringreplace,qualities,qualities,|,,
   if qualities=37
      asf=[1920*1080]
   if qualities=22
      asf=[1280* 720]
   if qualities=35
      asf=[640 * 480]
   if qualities=34
      asf=[640 * 360]
   if qualities=18
      asf=[480 * 360]
   if qualities=5
      asf:=" [320 * 240]"
   Gui,2: add, radio,x%x1% y%y1% hwndradio%A_index% vACR%qualities% gSTT1,FMT=%qualities%  %asf%
   }

I=0
asf=

;control, check,,,ahk_id %radio1%   ;-- << jump to highest quality and start
return
;-----------------------------------------------------------------

STT1:
Gui,2:submit,nohide
if ACR37=1
   {
   fmt=37
   goto,aa2
   }

if ACR22=1
   {
   fmt=22
   goto,aa2
   }

if ACR35=1
   {
   fmt=35
   goto,aa2
   }

if ACR34=1
   {
   fmt=34
   goto,aa2
   }

if ACR18=1
   {
   fmt=18
   goto,aa2
   }

if ACR5=1
   {
   fmt=5
   goto,aa2
   }


AA2:
extension := YTGetExtension(fmt)
c2:=% title . "." . extension

f21   =%recxx%\%c2%
f02  := % YTGetDownloadURL(ytSource,fmt)
S21  :=HttpQueryInfo(f02,5)                     ;-- << check size before

settimer,aas4,500
GuiControl,2:+RANGE0-%S21%,PRBAR                 ;CHANGE processbar
GuiControl,2:,title1,... running ...


;msgbox, 262208,MSGBOX,FMT=%fmt%`nTitle=%c2%
;return
;GuiControl,2:,Title1,DOWNLOADS >> %c2%

UrlDownloadToFile, % YTGetDownloadURL(ytSource,fmt),%f21%
settimer,AAS4,off
Filegetsize,size11,%f21%
if (S21=SIZE11)
   GuiControl,2:,title1,FINISHED succes
 else
   GuiControl,2:,title1,finished NO succes
GuiControl,2:,PRBAR, %SIZE11%

;run,%recxx%                             ;-- << opens folder when download finished
;run,%f21%                               ;-- << run video
return
;-------------------------------------------------------------------





aas4:
  Filegetsize,size11,%f21%
  RES1:=Round((100*SIZE11)/S21)
  GuiControl,2:,PRBAR, %SIZE11%
  GuiControl,2:,Title1,%RES1% `%  %c2%
return
;===========================================================




;================= function httpquery =======================

;http://www.autohotkey.com/forum/topic10510.html
HttpQueryInfo(URL, QueryInfoFlag=21, Proxy="", ProxyBypass="") {
hModule := DllCall("LoadLibrary", "str", "wininet.dll")

If (Proxy != "")
AccessType=3
Else
AccessType=1

io_hInternet := DllCall("wininet\InternetOpenA"
, "str", "" ;lpszAgent
, "uint", AccessType
, "str", Proxy
, "str", ProxyBypass
, "uint", 0) ;dwFlags
If (ErrorLevel != 0 or io_hInternet = 0) {
DllCall("FreeLibrary", "uint", hModule)
return, -1
}

iou_hInternet := DllCall("wininet\InternetOpenUrlA"
, "uint", io_hInternet
, "str", url
, "str", "" ;lpszHeaders
, "uint", 0 ;dwHeadersLength
, "uint", 0x80000000 ;dwFlags: INTERNET_FLAG_RELOAD = 0x80000000 // retrieve the original item
, "uint", 0) ;dwContext
If (ErrorLevel != 0 or iou_hInternet = 0) {
DllCall("FreeLibrary", "uint", hModule)
return, -1
}

VarSetCapacity(buffer, 1024, 0)
VarSetCapacity(buffer_len, 4, 0)

Loop, 5
{
  hqi := DllCall("wininet\HttpQueryInfoA"
  , "uint", iou_hInternet
  , "uint", QueryInfoFlag ;dwInfoLevel
  , "uint", &buffer
  , "uint", &buffer_len
  , "uint", 0) ;lpdwIndex
  If (hqi = 1) {
    hqi=success
    break
  }
}

IfNotEqual, hqi, success, SetEnv, res, timeout

If (hqi = "success") {
p := &buffer
Loop
{
  l := DllCall("lstrlen", "UInt", p)
  VarSetCapacity(tmp_var, l+1, 0)
  DllCall("lstrcpy", "Str", tmp_var, "UInt", p)
  p += l + 1
  res := res  . "`n" . tmp_var
  If (*p = 0)
  Break
}
StringTrimLeft, res, res, 1
}

DllCall("wininet\InternetCloseHandle",  "uint", iou_hInternet)
DllCall("wininet\InternetCloseHandle",  "uint", io_hInternet)
DllCall("FreeLibrary", "uint", hModule)
return, res
}
;======================================= END script =========================================================



Last edited by garry on March 28th, 2011, 9:30 am, edited 2 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 27th, 2011, 10:14 pm 
Offline

Joined: March 7th, 2011, 2:59 am
Posts: 151
Copied the following in a file called httpQuery.ahk
Code:
; exmpl.searchAHKforum.httpQuery.ahk
; Searches the forum for a given Phrase: in this case httpQuery
#noenv
html     := ""
URL      := "http://www.autohotkey.com/forum/search.php?mode=results"
POSTData := "search_keywords=httpQuery&search_terms=all&search_forum=-1&"
          . "search_time=0&search_fields=all&show_results=topics&return_chars=500"
          . "&sort_by=0&sort_dir=DESC"

length := httpQuery(html,URL,POSTdata)
varSetCapacity(html,-1)

Gui,Add,Edit,w600 +Wrap r25,% html
Gui,Show
Return

GuiClose:
GuiEscape:
   ExitApp
   
#include httpQuery.ahk


Copied the following in a file called YTLib.ahk:
Code:
; Author: flashkid
; thread: http://www.autohotkey.com/forum/viewtopic.php?t=34932

/*
 * This library provides basic youtube functions for downloading a video with correct title, extension, etc.
 * written by flashkid
 *
*/


/*
 * Extracts the title of a youtube video out of a given html source
 *
 * @param yt - html source
 * @return title
*/
YTGetTitle(yt) {
   RegExMatch(yt,"document\.title.*?""(.+?)"";", rtitle)      ;;;

/*
 * Extracts all available qualities of a youtube video out of a given html source
 *
 * @param yt - html source
 * @return pipe delimited quality list
*/
YTGetQualities(yt) {
   RegExMatch(yt,"fmt_url_map"": ""(.+?)""",content)                           ; extract content for qualities
   while (pos := RegExMatch(content1,"(.+?)\|.*?,",out,(pos ? pos : 1)))      ; cycle through available qualities
      q .= out1 "|", pos += StrLen(out), lpos := pos
   RegExMatch(content1,"(.+?)\|.*?",out,lpos)                                 ; catch last one too
   return q . out1
}

/*
 * Extracts the download url of a youtube video out of a given html source
 *
 * @param yt - html source
 * @param fmt - desired quality
 * @return download url
*/
YTGetDownloadURL(yt,fmt)
{
   RegExMatch(yt,"var swfConfig.*?" . fmt . "\|(.+?),", rurl)                     ; extract Download URL for fmt value
   toReplace = \u0026|&`n\/|/
   return replaceMultiple(rurl1,toReplace)
}

/*
 * Extracts the correct extension of a youtube video out of a given quality value
 *
 * @param fmt - quality
 * @return extension
*/
YTGetExtension(fmt) {
   static flv := "|5|34|35|", mp4 := "|18|22|37|38|", webm := "|43|45|", 3gp := "17", strings := "flv|mp4|webm|3gp"
   Loop, Parse, strings, |
      if InStr(%A_LoopField%,"|" . fmt . "|")
         return A_LoopField
}

/*
 * Replaces all occurences of input values with their desired replacements
 *
 * @param in - input variable
 * @param rep - linefeed delimited list of replacements in the format "value|replacement"
 * @return cleaned string
*/
replaceMultiple(in,rep) {
   Loop, Parse, rep, `n
   {
      StringSplit, var, A_LoopField, |
      StringReplace, in, in, %var1%, %var2%, ALL
   }
   return in
}


Copied the following in a file called YT Downloader.ahk
Code:
MODIFIED=20110327
;--- example GUI to flashkid's script youtube -----------------------------------------

#Include httpQuery.ahk    ;-- http://www.autohotkey.com/forum/viewtopic.php?t=33506
#Include YTLib.ahk        ;-- http://www.autohotkey.net/~flashkid/Youtube-Lib/YTLib.ahk
                          ;-- http://www.autohotkey.net/~flashkid/Youtube-Lib/YTLib.html
#NoEnv
SendMode Input
SetWorkingDir %A_ScriptDir%
RECXX        =c:\_A_INPUT              ;<<< record here
 IfNotExist, %RECXX%
     FileCreateDir, %RECXX%

;------- for test ------------------------------------------
c1=http://www.youtube.com/watch?v=nKKBmnIfQxg    ; portugal
;c1=http://www.youtube.com/watch?v=RVLJw-YL7y0    ; china
Gui,2: +AlwaysOnTop
Gui,2:Font, CDefault , Fixedsys
Gui,2:Add,Edit,x10 y2 w360 h20 vURL,
Gui,2:add,button, hidden default gA1,ok
Gui,2:add,button, x650 y3 h20 w100  gFolder1,FOLDER
Gui,2:Add,Edit, x10 y35  w750 h20 vTitle1 readonly   ,
Gui,2:Show,x10 y10 h95 w800,Youtube Adress  [Push ENTER to start and then select quality to download]
GuiControl,2:,URL,%c1%
Gui,2:Font, CDefault ,Arial
Return
;-----------------------------------------------------------------
2GuiClose:
ExitApp

Folder1:
Gui,2:submit,nohide
run,%recxx%
return
;-----------------------------------------------------------------

A1:
gui,2:submit,nohide
;msgbox, 262208,MSGBOX,%url%
if url=
   return

ytSource  := httpQuery(url)
title     := YTGetTitle(ytSource)
qualities := YTGetQualities(ytSource)
;extension := YTGetExtension(fmt)

I=0
X1=10
Y1=60
loop,parse,qualities,`|
   {
   I++
   if I=1
   x1:=(x1)
   else
   x1:=(x1+135)
   asf=
   qualities=
   stringmid,qualities,A_Loopfield,1,2
   stringreplace,qualities,qualities,|,,
   if qualities=37
      asf=[1920*1080]
   if qualities=22
      asf=[1280* 720]
   if qualities=35
      asf=[640 * 480]
   if qualities=34
      asf=[640 * 360]
   if qualities=18
      asf=[480 * 360]
   if qualities=5
      asf:=" [320 * 240]"
   Gui,2: add, radio,x%x1% y%y1% hwndradio%A_index% vACR%qualities% gSTT1,FMT=%qualities%  %asf%
   }

I=0
asf=

;control, check,,,ahk_id %radio1%   ;<< jump to highest quality and start
return
;-----------------------------------------------------------------

STT1:
Gui,2:submit,nohide
if ACR37=1
   {
   fmt=37
   goto,aa2
   }

if ACR22=1
   {
   fmt=22
   goto,aa2
   }

if ACR35=1
   {
   fmt=35
   goto,aa2
   }

if ACR34=1
   {
   fmt=34
   goto,aa2
   }

if ACR18=1
   {
   fmt=18
   goto,aa2
   }

if ACR5=1
   {
   fmt=5
   goto,aa2
   }


AA2:
extension := YTGetExtension(fmt)
c2:=% title . "." . extension
;msgbox, 262208,MSGBOX,FMT=%fmt%`nTitle=%c2%
;return
GuiControl,2:,Title1,DOWNLOADS >> %c2%
UrlDownloadToFile, % YTGetDownloadURL(ytSource,fmt),%recxx%\%c2%
GuiControl,2:,Title1,FINISHED
run,%recxx%                             ;<<< opens folder when download finished
return
;-------------------------------------------------------------------





; exmpl.searchAHKforum.httpQuery.ahk
; Searches the forum for a given Phrase: in this case httpQuery
#noenv
html     := ""
URL      := "http://www.autohotkey.com/forum/search.php?mode=results"
POSTData := "search_keywords=httpQuery&search_terms=all&search_forum=-1&"
          . "search_time=0&search_fields=all&show_results=topics&return_chars=500"
          . "&sort_by=0&sort_dir=DESC"

length := httpQuery(html,URL,POSTdata)
varSetCapacity(html,-1)

Gui,Add,Edit,w600 +Wrap r25,% html
Gui,Show
Return

GuiClose:
GuiEscape:
   ExitApp
   
#include httpQuery.ahk


Put all three in a test folder, and clicked on YT Downloader.ahk. DID NOT work! :?::arrow::!:


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 27th, 2011, 11:56 pm 
Offline

Joined: August 25th, 2007, 9:25 pm
Posts: 110
garry wrote:
tried to make a GUI around flashkid's script
( again to much goto's ... grrr )

must be checked ...
when I selected fmt=5 get a high quality video ( instead small size )

Sorry garry, updated the library. Nevertheless, you should really get rid of all your gotos, here is an example which is nearly half the code size:
Code:
MODIFIED=20110327
;--- example GUI to flashkid's script youtube -----------------------------------------

#Include httpQuery.ahk    ;-- http://www.autohotkey.com/forum/viewtopic.php?t=33506
#Include YTLib.ahk        ;-- http://www.autohotkey.net/~flashkid/Youtube-Lib/YTLib.ahk
                          ;-- http://www.autohotkey.net/~flashkid/Youtube-Lib/YTLib.html
#NoEnv
SendMode Input
SetWorkingDir %A_ScriptDir%
RECXX        = %A_ScriptDir%       ; I don't like scripts writing in other directories, especially without mentioning it

;------- for test ------------------------------------------
yturl =http://www.youtube.com/watch?v=nKKBmnIfQxg    ; portugal
;c1=http://www.youtube.com/watch?v=RVLJw-YL7y0    ; china
Gui, +AlwaysOnTop
Gui, Font, CDefault , Fixedsys
Gui, Add,Edit,x10 y2 w360 h20 vURL,
Gui, add,button, hidden default gStart,ok
Gui, add,button, x650 y3 h20 w100  gOpenFolder,FOLDER
Gui, Add,Edit, x10 y35  w750 h20 vStatus readonly   ,
Gui, Show,x10 y10 h95 w800,Youtube Adress  [Push ENTER to start and then select quality to download]
GuiControl,,URL,%yturl%
Gui, Font, CDefault ,Arial
Return
;-----------------------------------------------------------------
GuiClose:
ExitApp

OpenFolder:      ; using easy to remember and to identify label names
Gui,submit,nohide
run,%recxx%
return
;-----------------------------------------------------------------

Start:
gui,submit,nohide
if url=
   return
ytSource  := httpQuery(url)
title     := YTGetTitle(ytSource)
qualities := YTGetQualities(ytSource)

Loop, Parse, qualities, |               ; | doesn't need to be escaped
{
   x := 10 + 135 * (A_Index - 1)   ; calculating x position based on how often the loop ran
   if (A_LoopField = 37)            ; using expression form, just a matter of taste
      asf=[1920*1080]
   else if (A_LoopField = 22)
      asf=[1280* 720]
   else if (A_LoopField = 35)
      asf=[640 * 480]
   else if (A_LoopField = 34)
      asf=[640 * 360]
   else if (A_LoopField = 18)
      asf=[480 * 360]
   else if (A_LoopField = 5)
      asf=[320 * 240]
   Gui, add, radio,x%x% y60 hwndradio%A_Index% vACR%A_LoopField% gStartDownload,FMT=%A_LoopField%  %asf%
}
; control, check,,,ahk_id %radio1% ; << jump to highest quality and start
return
;-----------------------------------------------------------------

StartDownload:
Gui, submit,nohide
fmt := SubStr(A_GuiControl,4)   ; extract fmt value based on GuiControl name
extension := YTGetExtension(fmt)
filename := title . "." . extension      ; you do not need the % in expression mode :=
GuiControl,,Status,DOWNLOADS >> %filename%
UrlDownloadToFile, % YTGetDownloadURL(ytSource,fmt),%recxx%\%filename%
GuiControl,,Status,FINISHED
MsgBox, 4, Open Folder?, Do you want to open the folder?      ; like I said above, don't interrupt my work without asking
IfMsgBox Yes
   run,%recxx%                             ;<<< opens folder when download finished
return
;-------------------------------------------------------------------

I have commented a few things in code, but here are my thoughts about your coding style:
- you should use easily to remember and understand labels, variables, functions, etc.
- you should get rid of the many gotos
- you should keep one style of capitalization through the script (easier to read)
- you should not create folders, open folders, etc without asking the user
- you should use as few help variables as possible (in my opinion)

These are just my thoughts to help you writing easier to read and maintain code, don't be offended ;)


@bruno:
You have only copied the example and not the httpQuery function itself. You should have seen this, as in your code piece there is still a
Code:
#Include httpQuery.ahk
in your httpQuery.ahk, which doesn't make any sense.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 28th, 2011, 12:00 am 
Offline

Joined: March 7th, 2011, 2:59 am
Posts: 151
I included in my test folder the following:

httpQuery.ahk
Code:
#NoEnv

httpQueryOps = showheader
MsgBox % HTTPQuery(Result,"http://www.autohotkey.net/~Uberi/") . "`n""" . Result . """"

HTTPQuery(ByRef Result,URL,POSTData = "",Headers = "",POSTDataLength = "")
{
 ;Currently the verbs showHeader, storeHeader, and updateSize are supported in httpQueryOps. In case you need a different UserAgent, Proxy, ProxyBypass, Referrer, and AcceptType just specify them as global variables. Also if any special Flags are needed such as INTERNET_FLAG_NO_AUTO_REDIRECT or cache handling this might be set using the httpQueryDwFlags variable as global
 global httpQueryOps, httpAgent, httpProxy, httpProxyBypass, httpQueryReferrer, httpQueryAcceptType, httpQueryDwFlags, HttpQueryFullSize, HttpQueryHeader, HttpQueryCurrentSize
 CharSize := A_IsUnicode ? 2 : 1, Suffix := A_IsUnicode ? "W" : "A", UPtr := A_PtrSize ? "UPtr" : "UInt", Char := A_IsUnicode ? "UShort" : "UChar", PtrSize := A_PtrSize ? A_PtrSize : 4, StrGetFunc := "StrGet"

 If httpAgent =
  httpAgent = AutoHotkeyScript
 If httpProxy =
  httpProxy = 0
 If httpProxyBypass =
  httpProxyBypass = 0

 VarSetCapacity(URL_COMPONENTS,(6 * PtrSize) + 36,0), Offset := 0
 NumPut(60,URL_COMPONENTS,Offset,"UInt"), Offset += 4
 VarSetCapacity(lpszScheme,255,0), NumPut(&lpszScheme,URL_COMPONENTS,Offset), Offset += PtrSize, NumPut(255,URL_COMPONENTS,Offset,"UInt"), Offset += 4
 NumPut(255,URL_COMPONENTS,Offset,"UInt"), Offset += 4
 VarSetCapacity(lpszHostName,1024,0), NumPut(&lpszHostName,URL_COMPONENTS,Offset), Offset += PtrSize, NumPut(1024,URL_COMPONENTS,Offset,"UInt"), Offset += 4
 NumPut(0xFFFF,URL_COMPONENTS,Offset,"UInt"), Offset += 4
 VarSetCapacity(lpszUserName,1024,0), NumPut(&lpszUserName,URL_COMPONENTS,Offset), Offset += PtrSize, NumPut(1024,URL_COMPONENTS,Offset,"UInt"), Offset += 4
 VarSetCapacity(lpszPassword,1024,0), NumPut(&lpszPassword,URL_COMPONENTS,Offset), Offset += PtrSize, NumPut(1024,URL_COMPONENTS,Offset,"UInt"), Offset += 4
 VarSetCapacity(lpszURLPath,1024,0), NumPut(&lpszURLPath,URL_COMPONENTS,Offset), Offset += PtrSize, NumPut(1024,URL_COMPONENTS,Offset,"UInt"), Offset += 4
 VarSetCapacity(lpszExtraInfo,1024,0), NumPut(&lpszExtraInfo,URL_COMPONENTS,Offset), Offset += PtrSize, NumPut(1024,URL_COMPONENTS,Offset), Offset += 4
 hModule := DllCall("LoadLibrary","Str","WinINet.dll")
 ;Split the given URL: extract scheme, user, pass, authority (host), port, path, and query (extrainfo)
 If Not DllCall("WinINet\InternetCrackUrl" . Suffix,UPtr,&URL,"UInt",StrLen(URL),"UInt",0,UPtr,&URL_COMPONENTS)
  Return, "Error retrieving URL components."
 ;Update variables to length
 VarSetCapacity(lpszScheme,-1), VarSetCapacity(lpszHostName,-1), VarSetCapacity(lpszUserName,-1), VarSetCapacity(lpszPassword,-1), VarSetCapacity(lpszURLPath,-1), VarSetCapacity(lpszExtraInfo,-1)
 nPort := NumGet(URL_COMPONENTS,24)

 lpszUrlPath .= lpszExtrainfo

 ;detect additional Flags
 Flags := httpQueryDwFlags

 ;SECURITY_FLAG_IGNORE_UNKNOWN_CA=0x00000100
 ;SECURITY_FLAG_IGNORE_CERT_DATE_INVALID=0x00002000
 If lpszScheme = https
  Flags |= 0x801200 ;INTERNET_FLAG_SECURE | SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE

 ;detect unknown or invalid URL
 If lpszScheme = unknown
  Return, "Invalid URL."
 hInternet := DllCall("WinINet\InternetOpen" . Suffix,UPtr,&httpAgent,"UInt",(httpProxy ? 3 : 1),UPtr,&httpProxy,UPtr,&httpProxyBypass,"UInt",0)
 hConnect := DllCall("WinINet\InternetConnect" . Suffix,UPtr,hInternet,UPtr,&lpszHostname,"Int",nPort,UPtr,lpszUsername ? &lpszUsername : 0,UPtr,lpszPassword ? &lpszPassword : 0,"UInt",3,"UInt",0,"UInt*",0)
 If Not hConnect
  Return, "Connection failed."

 ;Select the correct HTTP verb
 If POSTData =
  HTTPVerb = GET
 Else
 {
  HTTPVerb = POST
  If Headers =
   Headers = Content-Type: application/x-www-form-urlencoded
 }

 hRequest := DllCall("WinINet\HttpOpenRequest" . Suffix,UPtr,hConnect,UPtr,&HTTPVerb,UPtr,&lpszUrlPath,"Str","HTTP/1.1",UPtr,&httpQueryReferrer,UPtr,&httpQueryAcceptTypes,"UInt",Flags,"UInt",0)
 If Not hRequest
  Return, "Error opening request."

 If Not DllCall("WinINet\HttpSendRequest" . Suffix, UPtr,hRequest,UPtr,Headers,"UInt",Strlen(Headers),UPtr,&POSTData,"UInt",(POSTDataLength <> "") ? POSTDataLength : Strlen(POSTData))
  Return, "Error sending request."

 VarSetCapacity(ReturnedHeaders,512,0), HeaderLen := 512
 Loop, 5
 {
  If (HeaderRequest := DllCall("WinINet\HttpQueryInfo" . Suffix,UPtr,hRequest,UInt,21,UPtr,&ReturnedHeaders,"UInt*",HeaderLen,"UInt",0))
   Break
  VarSetCapacity(ReturnedHeaders,HeaderLen,0)
 }
 If HeaderRequest
 {
  Loop, % HeaderLen / CharSize
  {
   If Not NumGet(ReturnedHeaders,(A_Index - 1) * CharSize,Char)
    NumPut(10,ReturnedHeaders,(A_Index - 1) * CharSize,Char) ;Asc("`n") = 10
  }
  VarSetCapacity(ReturnedHeaders,-1)
 }
 Else
  Return, "Timed out"

 Loop, Parse, ReturnedHeaders, `n, `r
 {
  RegExMatch(A_LoopField,"S)HTTP/1\.[01]\s+(\d+)",HTTPReturnValue)
  Break
 }

 ;HttpQueryOps handling
 If HTTPQueryOps <>
 {
  IfInString, HTTPQueryOps, ShowHeader ;show all returned headers
   MsgBox, %ReturnedHeaders%
  IfInString, HTTPQueryOps, StoreHeader ;store returned headers in a global variable
   HttpQueryHeader := ReturnedHeaders
  IfInString, HTTPQueryOps, UpdateSize ;store the size of the content in a global variable
  {
   If RegExMatch(A_LoopField,"\nContent-Length:\s*?(\d+)",HeaderSize)
    HttpQueryFullSize := HeaderSize1
   Else
    HttpQueryFullSize := "Size unavailable"
  }
 }

 If HTTPReturnValue1 Not In 100,200,201,202,302
 {
  HTTPReturnCodes = |100=Continue|101=Switching Protocols|102=Processing (WebDAV) (RFC 2518)|200=OK|201=Created|202=Accepted|203=Non-Authoritative Information|204=No Content|205=Reset Content|206=Partial Content|207=Multi-Status (WebDAV)|300=Multiple Choices|301=Moved Permanently|302=Found|303=See Other|304=Not Modified|305=Use Proxy|306=Switch Proxy|307=Temporary Redirect|400=Bad Request|401=Unauthorized|402=Payment Required|403=Forbidden|404=Not Found|405=Method Not Allowed|406=Not Acceptable|407=Proxy Authentication Required|408=Request Timeout|409=Conflict|410=Gone|411=Length Required|412=Precondition Failed|413=Request Entity Too Large|414=Request-URI Too Long|415=Unsupported Media Type|416=Requested Range Not Satisfiable|417=Expectation Failed|418=I'm a teapot (RFC 2324)|422=Unprocessable Entity (WebDAV) (RFC 4918)|423=Locked (WebDAV) (RFC 4918)|424=Failed Dependency (WebDAV) (RFC 4918)|425=Unordered Collection (RFC 3648)|426=Upgrade Required (RFC 2817)|449=Retry With|500=Internal Server Error|501=Not Implemented|502=Bad Gateway|503=Service Unavailable|504=Gateway Timeout|505=HTTP Version Not Supported|506=Variant Also Negotiates (RFC 2295)|507=Insufficient Storage (WebDAV) (RFC 4918)|509=Bandwidth Limit Exceeded|510=Not Extended (RFC 2774)|
  Temp1 := InStr(HTTPReturnCodes,"|" . HTTPReturnValue1 . "=")
  If Not Temp1
   Return, "Invalid return code"
  Temp1 += StrLen(HTTPReturnValue1) + 2, HTTPMessage := SubStr(HTTPReturnCodes,Temp1,InStr(HTTPReturnCodes,"|",False,Temp1) - Temp1), Result := HTTPReturnValue1 . " " . HTTPMessage
  Return, StrLen(Result)
 }

 TotalSize := 0, BytesRead := 0
 Loop
 {
  BufferIndex := A_Index
  VarSetCapacity(Buffer%BufferIndex%,1024,0)
  ReadFile := DllCall("wininet\InternetReadFile",UPtr,hRequest,UPtr,&Buffer%BufferIndex%,"UInt",1024,"UInt*",BytesRead)
  If (ReadFile && !BytesRead)
   Break
  Else
   TotalSize += BytesRead, SizeArray .= BytesRead . "|"
 }
 If InStr(HTTPQueryOps,"UpdateSize")
  HttpQueryCurrentSize := TotalSize
 SizeArray := SubStr(SizeArray,1,-1)

 VarSetCapacity(Result,TotalSize + 1,0)
 pData := &Result
 Loop, Parse, SizeArray, |
  DllCall("RtlMoveMemory",UPtr,pData,UPtr,&buffer%A_Index%,"UInt",A_LoopField), pData += A_LoopField

 IsText := RegExMatch(ReturnedHeaders,"iS)\nContent-Type:.*?\btext\b.*?(?:\bcharset=\K[\w-]+|$\K)",CharSet)
 pData := &Result
 ;check for a byte order mark
 If ((NumGet(Result) & 0xFFFFFF) = 0xBFBBEF) ;UTF-8 BOM: EF BB BF
  pData += 3, CharSet := "utf-8"
 Else If (NumGet(Result) & 0xffff) = 0xFEFF ; UTF-16 BOM: FF FE
  pData += 2, CharSet := "utf-16"
 If CharSet In utf-8,utf-16
 {
  If IsFunc("StrGet")
   Result := %StrGetFunc%(pData,CharSet)
  Else
  {
   If CharSet = utf-8
   {
    CharCount := DllCall("MultiByteToWideChar","UInt",65001,"UInt",0,UPtr,pData,"Int",-1,"UInt",0,"Int",0)
    VarSetCapacity(Temp1,CharCount << 1), DllCall("MultiByteToWideChar","UInt",65001,"UInt",0,UPtr,pData,"Int",CharCount,UPtr,&Temp1,"Int",CharCount << 1)
    DllCall("WideCharToMultiByte","UInt",0,"UInt",0x400,UPtr,&Temp1,"Int",CharCount,UPtr,&Result,"Int",CharCount,"UInt",0,"UInt",0), VarSetCapacity(Result,-1)
   }
   Else
   {
    CharCount := DllCall("WideCharToMultiByte","UInt",0,"UInt",0x400,UPtr,pData,"Int",-1,"UInt",0,"UInt",0,"UInt",0,"UInt",0)
    DllCall("WideCharToMultiByte","UInt",0,"UInt",0x400,UPtr,pData,"Int",CharCount,UPtr,&Result,"Int",CharCount,"UInt",0,"UInt",0), VarSetCapacity(Result,-1)
   }
  }
 }
 ;treat all unrecognized names as this system's ANSI code page.
 Else If (IsText && A_IsUnicode)
  Result := %StrGetFunc%(pData,"CP0")
 DllCall("WinINet\InternetCloseHandle",UPtr,hRequest), DllCall("WinINet\InternetCloseHandle",UPtr,hInternet), DllCall("WinINet\InternetCloseHandle",UPtr,hConnect), DllCall("FreeLibrary",UPtr,hModule)
 Return, TotalSize
}


YTLib.ahk
Code:
YTGetTitle(yt) {

    RegExMatch(yt,"document\.title.*?""(.+?)"";", rtitle)        ; extract title

    toReplace = \u00fc|ü`n\u00f6|ö`n\u00e4|ä`n\u00dc|Ü`n\u00d6|Ö`n\u00c4|Ä`n\u00df|ß`n&quot;|`n&amp;|&`n:|-`n*|_`n?|`n"|'`n/|_`n\|_`nÃo|Ü`nÃ-|Ö`nÃ"|Ä`nü|ü`nö|ö`nä|ä`nÃY|ß`n・|_

    replaced := replaceMultiple(rtitle1,toReplace)                ; replace above characters

    return RegExReplace(replaced,"[\\\/:\*\?""<>\|]","_")    ; replace illegal characters in filenames

}

YTGetQualities(yt) {

    RegExMatch(yt,"fmt_url_map"": ""(.+?)""",content)                                    ; extract content for qualities

    while (pos := RegExMatch(content1,"(.+?)\|.*?,",out,(pos ? pos : 1)))        ; cycle through available qualities

        q .= out1 "|", pos += StrLen(out), lpos := pos

    RegExMatch(content1,"(.+?)\|.*?",out,lpos)                                            ; catch last one too

    return q . out1

}

YTGetDownloadURL(yt,fmt)

{

    RegExMatch(yt,"var swfConfig.*?" . fmt . "\|(.+?),", rurl)                            ; extract Download URL for fmt value

    toReplace = \u0026|&`n\/|/

    return replaceMultiple(rurl1,toReplace)

}

YTGetExtension(fmt) {

    static flv := "|5|34|35|", mp4 := "|18|22|37|38|", webm := "|43|45|", 3gp := "17", strings := "flv|mp4|webm|3gp"

    Loop, Parse, strings, |

        if InStr(%A_LoopField%,"|" . fmt . "|")

            return A_LoopField

}

replaceMultiple(in,rep) {

    Loop, Parse, rep, `n

    {

        StringSplit, var, A_LoopField, |

        StringReplace, in, in, %var1%, %var2%, ALL

    }

    return in

}


It still does not work. :?: :lol:


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 28th, 2011, 12:04 am 
Offline

Joined: August 25th, 2007, 9:25 pm
Posts: 110
Please use the complete library file, so you know who has written the code and where you can find additional infos about it.
Furthermore, be more specific what is not working. The script in my previous post is fully functional as soon as you place httpQuery.ahk and YTLib.ahk inside the script's folder.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 28th, 2011, 12:10 am 
Offline

Joined: March 7th, 2011, 2:59 am
Posts: 151
Thanks, but the full lib in the link is not correctly encoded in the browser and has corrupted chars in it. :lol:

Code:
YTGetTitle(yt) {
   RegExMatch(yt,"document\.title.*?""(.+?)"";", rtitle)      ; extract title
   toReplace = \u00fc|�`n\u00f6|�`n\u00e4|�`n\u00dc|�`n\u00d6|�`n\u00c4|�`n\u00df|�`n&quot;|`n&amp;|&`n:|-`n*|_`n?|`n"|'`n/|_`n\|_`n�o|�`n�-|�`n�"|�`nü|�`nö|�`nä|�`n�Y|�`n・|_
   replaced := replaceMultiple(rtitle1,toReplace)            ; replace above characters
   return RegExReplace(replaced,"[\\\/:\*\?""<>\|]","_")   ; replace illegal characters in filenames
}


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 28th, 2011, 12:11 am 
Offline

Joined: August 25th, 2007, 9:25 pm
Posts: 110
Right click on the link -> Save as


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 28th, 2011, 1:14 am 
Offline

Joined: March 7th, 2011, 2:59 am
Posts: 151
Thanks! Now it works! :lol:

YT Downloader.ahk
Code:
MODIFIED=20110327

;--- example GUI to flashkid's script youtube ---

#Include httpQuery.ahk ;--- http://www.autohotkey.com/forum/viewtopic.php?t=33506
#Include YTLib.ahk ;--- http://www.autohotkey.net/~flashkid/Youtube-Lib/YTLib.ahk
;--- http://www.autohotkey.net/~flashkid/Youtube-Lib/YTLib.html

#NoEnv
SendMode Input
SetWorkingDir %A_ScriptDir%
RECXX        =c:\_A_INPUT ; << record here
 IfNotExist, %RECXX%
     FileCreateDir, %RECXX%

;--- for test ---

c1=http://www.youtube.com/watch?v=nKKBmnIfQxg ; portugal
;c1=http://www.youtube.com/watch?v=RVLJw-YL7y0 ; china
Gui,2: +AlwaysOnTop
Gui,2:Font, CDefault , Fixedsys
Gui,2:Add,Edit,x10 y2 w360 h20 vURL,
Gui,2:add,button, hidden default gA1,ok
Gui,2:add,button, x650 y3 h20 w100  gFolder1,FOLDER
Gui,2:Add,Edit, x10 y35  w750 h20 vTitle1 readonly   ,
Gui,2:Show,x10 y10 h95 w800,Youtube Address [Press ENTER to start and then select FMT to download]
GuiControl,2:,URL,%c1%
Gui,2:Font, CDefault ,Arial
Return

;---

2GuiClose:
ExitApp

Folder1:
Gui,2:submit,nohide
run,%recxx%
return

;---

A1:
gui,2:submit,nohide
;msgbox, 262208,MSGBOX,%url%
if url=
   return

ytSource  := httpQuery(url)
title     := YTGetTitle(ytSource)
qualities := YTGetQualities(ytSource)
;extension := YTGetExtension(fmt)

I=0
X1=10
Y1=60
loop,parse,qualities,`|
   {
   I++
   if I=1
   x1:=(x1)
   else
   x1:=(x1+135)
   asf=
   qualities=
   stringmid,qualities,A_Loopfield,1,2
   stringreplace,qualities,qualities,|,,
   if qualities=37
      asf=[1920*1080]
   if qualities=22
      asf=[1280* 720]
   if qualities=35
      asf=[640 * 480]
   if qualities=34
      asf=[640 * 360]
   if qualities=18
      asf=[480 * 360]
   if qualities=5
      asf:=" [320 * 240]"
   Gui,2: add, radio,x%x1% y%y1% hwndradio%A_index% vACR%qualities% gSTT1,FMT=%qualities%  %asf%
   }

I=0
asf=

;control, check,,,ahk_id %radio1% ; << jump to highest quality and start
return

;---

STT1:
Gui,2:submit,nohide
if ACR37=1
   {
   fmt=37
   goto,aa2
   }

if ACR22=1
   {
   fmt=22
   goto,aa2
   }

if ACR35=1
   {
   fmt=35
   goto,aa2
   }

if ACR34=1
   {
   fmt=34
   goto,aa2
   }

if ACR18=1
   {
   fmt=18
   goto,aa2
   }

if ACR5=1
   {
   fmt=5
   goto,aa2
   }


AA2:
extension := YTGetExtension(fmt)
c2:=% title . "." . extension
;msgbox, 262208,MSGBOX,FMT=%fmt%`nTitle=%c2%
;return
GuiControl,2:,Title1,DOWNLOAD >> %c2%
UrlDownloadToFile, % YTGetDownloadURL(ytSource,fmt),%recxx%\%c2%
GuiControl,2:,Title1,FINISHED
run,%recxx% ; << opens folder when download finished
return

;---


httpQuery.ahk
Code:
; httpQuery-0-3-6.ahk

httpQuery(byref p1 = "", p2 = "", p3="", p4="")
{  ; v0.3.6 (w) Oct, 26 2010 by derRaphael / zLib-Style release
   ; currently the verbs showHeader, storeHeader, and updateSize are supported in httpQueryOps
   ; in case u need a different UserAgent, Proxy, ProxyByPass, Referrer, and AcceptType just
   ; specify them as global variables - mind the varname for referrer is httpQueryReferer [sic].
   ; Also if any special dwFlags are needed such as INTERNET_FLAG_NO_AUTO_REDIRECT or cache
   ; handling this might be set using the httpQueryDwFlags variable as global, global httpQueryOps, httpAgent, httpProxy, httpProxyByPass, httpQueryReferer, httpQueryAcceptType, httpQueryDwFlags
   ; Get any missing default Values
   
   ; v0.3.6
   ; Check for syntax
   if ( VarSetCapacity(p1) != 0 )
      dReturn:=true,  result := "", lpszUrl := p1, POSTDATA := p2, HEADERS  := p3
   else
      result := p1, lpszUrl := p2, POSTDATA := p3, HEADERS  := p4
   
   defaultOps =
   (LTrim Join|
      httpAgent=AutoHotkeyScript|httpProxy=0|httpProxyByPass=0|INTERNET_FLAG_SECURE=0x00800000
      SECURITY_FLAG_IGNORE_UNKNOWN_CA=0x00000100|SECURITY_FLAG_IGNORE_CERT_CN_INVALID=0x00001000
      SECURITY_FLAG_IGNORE_CERT_DATE_INVALID=0x00002000|SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE=0x00000200
      INTERNET_OPEN_TYPE_PROXY=3|INTERNET_OPEN_TYPE_DIRECT=1|INTERNET_SERVICE_HTTP=3
   )
   Loop,Parse,defaultOps,|
   {
      RegExMatch(A_LoopField,"(?P<Option>[^=]+)=(?P<Default>.*)",http)
      if StrLen(%httpOption%)=0
         %httpOption% := httpDefault
   }

   ; Load Library
   hModule := DllCall("LoadLibrary", "Str", "WinINet.Dll")

   ; SetUpStructures for URL_COMPONENTS / needed for InternetCrackURL
   ; http://msdn.microsoft.com/en-us/library/aa385420(VS.85).aspx
   offset_name_length:= "4-lpszScheme-255|16-lpszHostName-1024|28-lpszUserName-1024|"
                  . "36-lpszPassword-1024|44-lpszUrlPath-1024|52-lpszExtrainfo-1024"
   VarSetCapacity(URL_COMPONENTS,60,0)
   ; Struc Size               ; Scheme Size                  ; Max Port Number
   NumPut(60,URL_COMPONENTS,0), NumPut(255,URL_COMPONENTS,12), NumPut(0xffff,URL_COMPONENTS,24)
   
   Loop,Parse,offset_name_length,|
   {
      RegExMatch(A_LoopField,"(?P<Offset>\d+)-(?P<Name>[a-zA-Z]+)-(?P<Size>\d+)",iCU_)
      VarSetCapacity(%iCU_Name%,iCU_Size,0)
      NumPut(&%iCU_Name%,URL_COMPONENTS,iCU_Offset)
      NumPut(iCU_Size,URL_COMPONENTS,iCU_Offset+4)
   }

   ; Split the given URL; extract scheme, user, pass, authotity (host), port, path, and query (extrainfo)
   ; http://msdn.microsoft.com/en-us/library/aa384376(VS.85).aspx
   DllCall("WinINet\InternetCrackUrlA","Str",lpszUrl,"uInt",StrLen(lpszUrl),"uInt",0,"uInt",&URL_COMPONENTS)

   ; Update variables to retrieve results
   Loop,Parse,offset_name_length,|
   {
      RegExMatch(A_LoopField,"-(?P<Name>[a-zA-Z]+)-",iCU_)
      VarSetCapacity(%iCU_Name%,-1)
   }
   nPort:=NumGet(URL_COMPONENTS,24,"uInt")
   
   ; Import any set dwFlags
   dwFlags := httpQueryDwFlags
   ; For some reasons using a selfsigned https certificates doesnt work
   ; such as an own webmin service - even though every security is turned off
   ; https with valid certificates works when
   if (lpszScheme = "https")
      dwFlags |= (INTERNET_FLAG_SECURE|SECURITY_FLAG_IGNORE_CERT_CN_INVALID
               |SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE)

   ; Check for Header and drop exception if unknown or invalid URL
   if (lpszScheme="unknown") {
      Result := "ERR: No Valid URL supplied."
      Return StrLen(Result)
   }

   ; Initialise httpQuery's use of the WinINet functions.
   ; http://msdn.microsoft.com/en-us/library/aa385096(VS.85).aspx
   hInternet := DllCall("WinINet\InternetOpenA"
                  ,"Str",httpAgent,"UInt"
                  ,(httpProxy != 0 ?  INTERNET_OPEN_TYPE_PROXY : INTERNET_OPEN_TYPE_DIRECT )
                  ,"Str",httpProxy,"Str",httpProxyBypass,"Uint",0)

   ; Open HTTP session for the given URL
   ; http://msdn.microsoft.com/en-us/library/aa384363(VS.85).aspx
   hConnect := DllCall("WinINet\InternetConnectA"
                  ,"uInt",hInternet,"Str",lpszHostname, "Int",nPort
                  ,"Str",lpszUserName, "Str",lpszPassword,"uInt",INTERNET_SERVICE_HTTP
                  ,"uInt",0,"uInt*",0)

   ; Do we POST? If so, check for header handling and set default
   if (Strlen(POSTDATA)>0) {
      HTTPVerb:="POST"
      if StrLen(Headers)=0
         Headers:="Content-Type: application/x-www-form-urlencoded"
   } else ; otherwise mode must be GET - no header defaults needed
      HTTPVerb:="GET"   

   ; Form the request with proper HTTP protocol version and create the request handle
   ; http://msdn.microsoft.com/en-us/library/aa384233(VS.85).aspx
   hRequest := DllCall("WinINet\HttpOpenRequestA"
                  ,"uInt",hConnect,"Str",HTTPVerb,"Str",lpszUrlPath . lpszExtrainfo
                  ,"Str",ProVer := "HTTP/1.1", "Str",httpQueryReferer,"Str",httpQueryAcceptTypes
                  ,"uInt",dwFlags,"uInt",Context:=0 )

   ; Send the specified request to the server
   ; http://msdn.microsoft.com/en-us/library/aa384247(VS.85).aspx
   sRequest := DllCall("WinINet\HttpSendRequestA"
                  , "uInt",hRequest,"Str",Headers, "uInt",Strlen(Headers)
                  , "Str",POSTData,"uInt",Strlen(POSTData))

   VarSetCapacity(header, 2048, 0)  ; max 2K header data for httpResponseHeader
   VarSetCapacity(header_len, 4, 0)
   
   ; Check for returned server response-header (works only _after_ request been sent)
   ; http://msdn.microsoft.com/en-us/library/aa384238.aspx
   Loop, 5
     if ((headerRequest:=DllCall("WinINet\HttpQueryInfoA","uint",hRequest
      ,"uint",21,"uint",&header,"uint",&header_len,"uint",0))=1)
      break

   If (headerRequest=1) {
      VarSetCapacity(res,headerLength:=NumGet(header_len),32)
      DllCall("RtlMoveMemory","uInt",&res,"uInt",&header,"uInt",headerLength)
      Loop,% headerLength
         if (*(&res-1+a_index)=0) ; Change binary zero to linefeed
            NumPut(Asc("`n"),res,a_index-1,"uChar")
      VarSetCapacity(res,-1)
   } else
      res := "timeout"

   ; Get 1st Line of Full Response
   Loop,Parse,res,`n,`r
   {
      RetValue := A_LoopField
      break
   }
   
   ; No Connection established - drop exception
   If (RetValue="timeout") {
      html := "Error: timeout"
      return -1
   }
   ; Strip protocol version from return value
   RetValue := RegExReplace(RetValue,"HTTP/1\.[01]\s+")
   
    ; List taken from http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
   HttpRetCodes := "100=Continue|101=Switching Protocols|102=Processing (WebDAV) (RFC 2518)|"
              . "200=OK|201=Created|202=Accepted|203=Non-Authoritative Information|204=No"
              . " Content|205=Reset Content|206=Partial Content|207=Multi-Status (WebDAV)"
              . "|300=Multiple Choices|301=Moved Permanently|302=Found|303=See Other|304="
              . "Not Modified|305=Use Proxy|306=Switch Proxy|307=Temporary Redirect|400=B"
              . "ad Request|401=Unauthorized|402=Payment Required|403=Forbidden|404=Not F"
              . "ound|405=Method Not Allowed|406=Not Acceptable|407=Proxy Authentication "
              . "Required|408=Request Timeout|409=Conflict|410=Gone|411=Length Required|4"
              . "12=Precondition Failed|413=Request Entity Too Large|414=Request-URI Too "
              . "Long|415=Unsupported Media Type|416=Requested Range Not Satisfiable|417="
              . "Expectation Failed|418=I'm a teapot (RFC 2324)|422=Unprocessable Entity "
              . "(WebDAV) (RFC 4918)|423=Locked (WebDAV) (RFC 4918)|424=Failed Dependency"
              . " (WebDAV) (RFC 4918)|425=Unordered Collection (RFC 3648)|426=Upgrade Req"
              . "uired (RFC 2817)|449=Retry With|500=Internal Server Error|501=Not Implem"
              . "ented|502=Bad Gateway|503=Service Unavailable|504=Gateway Timeout|505=HT"
              . "TP Version Not Supported|506=Variant Also Negotiates (RFC 2295)|507=Insu"
              . "fficient Storage (WebDAV) (RFC 4918)|509=Bandwidth Limit Exceeded|510=No"
              . "t Extended (RFC 2774)"
   
   ; Gather numeric response value
   RetValue := SubStr(RetValue,1,3)
   
   ; Parse through return codes and set according informations
   Loop,Parse,HttpRetCodes,|
   {
      HttpReturnCode := SubStr(A_LoopField,1,3)    ; Numeric return value see above
      HttpReturnMsg  := SubStr(A_LoopField,5)      ; link for additional information
      if (RetValue=HttpReturnCode) {
         RetMsg := HttpReturnMsg
         break
      }
   }

   ; Global HttpQueryOps handling
   if strlen(HTTPQueryOps)>0 {
      ; Show full Header response (usefull for debugging)
      if (instr(HTTPQueryOps,"showHeader"))
         MsgBox % res
      ; Save the full Header response in a global Variable
      if (instr(HTTPQueryOps,"storeHeader"))
         global HttpQueryHeader := res
      ; Check for size updates to export to a global Var
      if (instr(HTTPQueryOps,"updateSize")) {
         Loop,Parse,res,`n
            If RegExMatch(A_LoopField,"Content-Length:\s+?(?P<Size>\d+)",full) {
               global HttpQueryFullSize := fullSize
               break
            }
         if (fullSize+0=0)
            HttpQueryFullSize := "size unavailable"
      }
   }

   ; Check for valid codes and drop exception if suspicious
   if !(InStr("100 200 201 202 302",RetValue)) {
      Result := RetValue " " RetMsg
      return StrLen(Result)
   }

   VarSetCapacity(BytesRead,4,0)
   fsize := 0
   Loop            ; the receiver loop - rewritten in the need to enable
   {               ; support for larger file downloads
      bc := A_Index
      VarSetCapacity(buffer%bc%,1024,0) ; setup new chunk for this receive round
      ReadFile := DllCall("wininet\InternetReadFile"
                  ,"uInt",hRequest,"uInt",&buffer%bc%,"uInt",1024,"uInt",&BytesRead)
      ReadBytes := NumGet(BytesRead)    ; how many bytes were received?
      If ((ReadFile!=0)&&(!ReadBytes))  ; we have had no error yet and received no more bytes
         break                         ; we must be done! so lets break the receiver loop
      Else {
         fsize += ReadBytes            ; sum up all chunk sizes for correct return size
         sizeArray .= ReadBytes "|"
      }
      if (instr(HTTPQueryOps,"updateSize"))
         Global HttpQueryCurrentSize := fsize
   }
   sizeArray := SubStr(sizeArray,1,-1)   ; trim last PipeChar
   
   VarSetCapacity( ( dReturn == true ) ? result : p1 ,fSize+1,0)      ; reconstruct the result from above generated chunkblocks
   Dest := ( dReturn == true ) ? &result : &p1                 ; to a our ByRef result variable
   Loop,Parse,SizeArray,|
      DllCall("RtlMoveMemory","uInt",Dest,"uInt",&buffer%A_Index%,"uInt",A_LoopField)
      , Dest += A_LoopField
     
   DllCall("WinINet\InternetCloseHandle", "uInt", hRequest)   ; close all opened
   DllCall("WinINet\InternetCloseHandle", "uInt", hInternet)
   DllCall("WinINet\InternetCloseHandle", "uInt", hConnect)
   DllCall("FreeLibrary", "UInt", hModule)                    ; unload the library
   
   if ( dReturn == true ) {
      VarSetCapacity( result, -1 )
      ErrorLevel := fSize
      return Result
   } else
      return fSize                      ; return the size - strings need update via VarSetCapacity(res,-1)
}


YTLib.ahk
Code:
; Author: flashkid
; Thread: http://www.autohotkey.com/forum/viewtopic.php?t=34932


/*
 * This library provides basic youtube functions for downloading a video with correct title, extension, etc.
 * Written by flashkid
*/


/*
 * Extracts the title of a youtube video out of a given html source
 * @param yt - html source
 * @return title
*/


YTGetTitle(yt) {

    RegExMatch(yt,"document\.title.*?""(.+?)"";", rtitle) ; extract title

    toReplace = \u00fc|ü`n\u00f6|ö`n\u00e4|ä`n\u00dc|Ü`n\u00d6|Ö`n\u00c4|Ä`n\u00df|ß`n&quot;|`n&amp;|&`n:|-`n*|_`n?|`n"|'`n/|_`n\|_`nÃo|Ü`nÃ-|Ö`nÃ"|Ä`nü|ü`nö|ö`nä|ä`nÃY|ß`n・|_

    replaced := replaceMultiple(rtitle1,toReplace) ; replace above characters

    return RegExReplace(replaced,"[\\\/:\*\?""<>\|]","_") ; replace illegal characters in filenames

}


/*
 * Extracts all available qualities of a youtube video out of a given html source
 * @param yt - html source
 * @return pipe delimited quality list
*/


YTGetQualities(yt) {

    RegExMatch(yt,"fmt_url_map"": ""(.+?)""",content) ; extract content for qualities

    while (pos := RegExMatch(content1,"(.+?)\|.*?,",out,(pos ? pos : 1))) ; cycle through available qualities

        q .= out1 "|", pos += StrLen(out), lpos := pos

    RegExMatch(content1,"(.+?)\|.*?",out,lpos) ; catch last one too

    return q . out1

}


/*
 * Extracts the download url of a youtube video out of a given html source
 * @param yt - html source
 * @param fmt - desired quality
 * @return download url
*/


YTGetDownloadURL(yt,fmt) {

    RegExMatch(yt,"fmt_url_map"": ("".+?"")",content) ; extract content for urls

    RegExMatch(content1,"[,""]" . fmt . "\|(.+?)[,""]", rurl) ; extract Download URL for fmt value

    toReplace = \u0026|&`n\/|/

    return replaceMultiple(rurl1,toReplace)

}


/*
 * Extracts the correct extension of a youtube video out of a given quality value
 * @param fmt - quality
 * @return extension
*/


YTGetExtension(fmt) {

    static flv := "|5|34|35|", mp4 := "|18|22|37|38|", webm := "|43|45|", 3gp := "17", strings := "flv|mp4|webm|3gp"

    Loop, Parse, strings, |

        if InStr(%A_LoopField%,"|" . fmt . "|")

            return A_LoopField

}


/*
 * Replaces all occurences of input values with their desired replacements
 * @param in - input variable
 * @param rep - linefeed delimited list of replacements in the format "value|replacement"
 * @return cleaned string
*/


replaceMultiple(in,rep) {

    Loop, Parse, rep, `n

    {

        StringSplit, var, A_LoopField, |

        StringReplace, in, in, %var1%, %var2%, ALL

    }

    return in

}


Last edited by bruno on March 28th, 2011, 3:50 am, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 28th, 2011, 3:45 am 
Offline

Joined: March 7th, 2011, 2:59 am
Posts: 151
One problem I found with the GUI is that when I select FMT, it flashes this error message: Error: The same variable cannot be used for more than one control. The current thread will exit.

--> Gui,2: add, radio, x%x1% y%y1% hwndradio%A_index% vACR%qualities% gSTT1, FMT=%qualities% %asf%

But after I dismiss this error message (pressing OK), it somehow downloads the selected file anyway!? :roll:
PS: I just discovered I get the above Error because I hit Enter after I select FMT (quality). So, just select one of the FMT radio buttons and wait for the download. DO NOT press Enter after that! :oops: :lol:


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 28th, 2011, 6:13 am 
Offline

Joined: March 7th, 2011, 2:59 am
Posts: 151
I did some GUI (linguistic, mainly) clean-up of garry's great work... THIS could easily surpass all the previous YT downloaders as the most compact and no-nonsense, no-frills piece of software. :lol:

Code:
MODIFIED=20110327

;--- example GUI to flashkid's script youtube ---

#Include httpQuery.ahk ;--- http://www.autohotkey.com/forum/viewtopic.php?t=33506
#Include YTLib.ahk ;--- http://www.autohotkey.net/~flashkid/Youtube-Lib/YTLib.ahk

;--- http://www.autohotkey.net/~flashkid/Youtube-Lib/YTLib.html

#NoEnv
SendMode Input
SetWorkingDir %A_ScriptDir%
RECXX=C:\Docume~1\HP_Adm~1\MyDocu~1\051809\AutoHo~1\Downlo~1 ; << Record here
;RECXX=c:\_A_INPUT ; << Record here
;IfNotExist, %RECXX%
;FileCreateDir, %RECXX%

;--- for test ---

;c1=http://www.youtube.com/watch?v=nKKBmnIfQxg ; portugal
;c1=http://www.youtube.com/watch?v=RVLJw-YL7y0 ; china
;Gui,2: +AlwaysOnTop

Gui,2: Font, CDefault, Fixedsys
Gui,2: Add, Edit, x10 y2 w360 h20 vURL,
Gui,2: add, button, hidden default gA1, ok
Gui,2: add, button, x650 y3 h20 w100  gFolder1, FOLDER
Gui,2: Add, Edit, x10 y35 w750 h20 vTitle1 readonly,
Gui,2: Show, x10 y10 h95 w800, Youtube Address [Press ENTER to start and then select FMT to download]
GuiControl,2:,URL,%c1%
Gui,2: Font, CDefault, Arial
Return

;---

2GuiClose:
ExitApp

Folder1:
Gui,2: submit, nohide
run,%recxx% ; Opens folder when clicking GUI FOLDER button
return

;---

A1:
gui,2: submit, nohide
;msgbox, 262208, MSGBOX, %url%
if url=
return

ytSource := httpQuery(url)
title := YTGetTitle(ytSource)
qualities := YTGetQualities(ytSource)
;extension := YTGetExtension(fmt)

I=0
X1=10
Y1=60
loop,parse,qualities,`|
   {
   I++
   if I=1
   x1:=(x1)
   else
   x1:=(x1+135)
   asf=
   qualities=
   stringmid,qualities,A_Loopfield,1,2
   stringreplace,qualities,qualities,|,,
   if qualities=37
      asf=[1920 * 1080]
   if qualities=22
      asf=[1280 * 720]
   if qualities=35
      asf=[640 * 480]
   if qualities=34
      asf=[640 * 360]
   if qualities=18
      asf=[480 * 360]
   if qualities=5
      asf=[320 * 240]
;  if qualities=5
;     asf:="[320 * 240]"
Gui,2: add, radio, x%x1% y%y1% hwndradio%A_index% vACR%qualities% gSTT1, FMT = %qualities% %asf%
   }
I=0
asf=

;control, check,,,ahk_id %radio1% ; << Jump to highest quality and start
return

;---

STT1:
Gui,2: submit, nohide
if ACR37=1
   {
   fmt=37
   goto,aa2
   }

if ACR22=1
   {
   fmt=22
   goto,aa2
   }

if ACR35=1
   {
   fmt=35
   goto,aa2
   }

if ACR34=1
   {
   fmt=34
   goto,aa2
   }

if ACR18=1
   {
   fmt=18
   goto,aa2
   }

if ACR5=1
   {
   fmt=5
   goto,aa2
   }
AA2:
extension := YTGetExtension(fmt)
c2:=% title . "." . extension
;msgbox, 262208, MSGBOX, FMT=%fmt%`nTitle=%c2%
;return
GuiControl,2:,Title1, DOWNLOADING... >> %c2%
UrlDownloadToFile,% YTGetDownloadURL(ytSource,fmt),%recxx%\%c2% ; Space after % and before YT...
GuiControl,2:,Title1,DOWNLOAD COMPLETED!
run,%recxx% ; << Opens folder when download finished
return

;---


Last edited by bruno on March 28th, 2011, 8:08 am, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 28th, 2011, 7:08 am 
Offline

Joined: April 19th, 2005, 10:26 am
Posts: 2250
Location: switzerland
thank you flashkid for your comments and professional good short script
youtube often changes and glad to get help here
I tried with conventional ahk commands, script much more longer then with regex and functions
sorry , didn't make effort to learn regex and functions yet ... I know I should and can learn from your good scripts

some commands I made to see what happen and where are videos (?)
( you can delete them )

Code:
recxx        =c:\_A_INPUT                 ;-- << record here ( and not have big files in a_scriptdir )
;..........
Gui,2:add,button, x650 y3 h20 w100  gFolder1,FOLDER   ;-- << I often missing this button ( where are my videos ? )
;.........
GuiControl,2:,Title1,DOWNLOADS >> %c2%    ;-- << see running
UrlDownloadToFile, % YTGetDownloadURL(ytSource,fmt),%recxx%\%c2%
GuiControl,2:,Title1,FINISHED             ;-- << see when finished
run,%recxx%                               ;-- << maybe open folder when download finished


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 28th, 2011, 7:14 am 
Offline

Joined: March 7th, 2011, 2:59 am
Posts: 151
garry, thank! How can I add a button to your GUI so that once you have entered the YT URL in the box, you can then click GO or DOWNLOAD rather than pressing the Enter key? :lol:


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 137 posts ]  Go to page Previous  1 ... 4, 5, 6, 7, 8, 9, 10  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: Bon and 12 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group