AutoHotkey Community

It is currently May 26th, 2012, 1:57 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 29 posts ]  Go to page Previous  1, 2
Author Message
 Post subject:
PostPosted: December 30th, 2007, 7:09 pm 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
Thanks engunneer. By the looks of that list, its a bit out of date, and there seem to be a lot of important changes missing, and a lot of unnecessary ones included.

bmcclure, I think the function should look like this. I went on how I remember my old one looking like as I couldnt find it. Perhaps its on my hard drive that broke :? Anyway Ive included the function and a gui so you can see its features. I barely did any testing, so it might need some tweaking.


Code:
Space := "                                                     "
Gui, 1: Add, Button, x10 y10 w75 r1 -Multi -Wrap gRead Default, &Torrent
Gui, 1: Add, ListView, x10 y+20 w600 h400, File %Space%%Space%%Space%|Size (KB)
Gui, 1: Add, Text, x10 y470 w200 r1 -Multi -Wrap, Announce URLs:
Gui, 1: Add, Edit, x10 y+10 w295 h100 vAnnounce
Gui, 1: Add, Text, x+10 y470 w200 r1 -Multi -Wrap, Comments:
Gui, 1: Add, Edit, x315 y+10 w295 h100 vComment
Gui, 1: Show, AutoSize
Return

Read:
AnnounceURL := ""
Gui, 1: +OwnDialogs
FileSelectFile, Torrent,,, Select Torrent to read, Torrents (*.torrent)
If ErrorLevel
Return
LV_Delete()
TorrentRead(Torrent, "Data", "Size", "Announce", "Comment")
Loop, %Data0%
LV_Add("", Data%A_Index%, Size%A_Index%//1024)
Loop, %Announce0%
AnnounceURL .= Announce%A_Index% "`n"
GuiControl,, Announce, %AnnounceURL%
GuiControl,, Comment, %Comment%
Return

;#######################################################################################
; Torrent: Path to torrent
; Files: Variable to put names of torrent files into. Variable0 contains number of files
; Size: Variable to put sizes of files into. Variable0 contains number of files, same as above
; Announce: Variable to put announce url into. Variable0 contains number of urls
; TorrentComment: Variable to put the comment for the torrent into

TorrentRead(Torrent, Files="", Size="", Announce="", TorrentComment="")
{    
   Local Data,Name,Name1,Name2,StrOffset,FileName,Num,Loc,Loc1,URL,URL1,Tracker,RetComment,RetComment1,Bytes,Bytes1

   FileRead, Data, %Torrent%
   RegExMatch(Data, "4:name([0-9]+):(.+?):", Name)
   Name := Substr(Name2, 1, Name1)
   
   If Announce
   {
      StrOffset := 1
      Loop
      {
         If A_Index = 1
         StrOffset := RegExMatch(Data, "announce([0-9]+):", URL, StrOffset)
         Else
         StrOffset := RegExMatch(Data, "([0-9]+):", URL, StrOffset)
         Tracker := SubStr(Data, StrOffset+StrLen(URL), URL1)
         If Tracker contains http,udp
         {
            Num++
            %Announce%%Num% := Tracker, StrOffset := StrOffset+StrLen(URL)+URL1
         }
         Else If (Tracker = "announce-list")
         StrOffset := StrOffset+StrLen(URL)+URL1
         Else
         Break   
      }
      %Announce%0 := Num
   }
   
   If TorrentComment
   StrOffset := RegExMatch(Data, "comment([0-9]+):", RetComment), %TorrentComment% := SubStr(Data, StrOffset+StrLen(RetComment), RetComment1)
   
   StrOffset := 1, Num := ""
   Loop
   {
      If Size
      RegExMatch(Data, "6:lengthi([0-9]+)e", Bytes, StrOffset)
      StrOffset := InStr(Data, "4:path", 0, StrOffset) + 6
      If StrOffset = 6
      {
         If A_Index = 1
         %Files%0 := 1, %Files%1 := Name
         Else
         %Files%0 := Num
         If Size
         %Size%0 := %Files%0
         Return
      }

      FileName := Name
      Loop
      {
         If (SubStr(Data, StrOffset, 1) = "e")
         Break   
         StrOffset := RegExMatch(Data, "([0-9]+):", Loc, StrOffset)
         FileName .= "\" SubStr(Data, StrOffset+StrLen(Loc), Loc1), StrOffset := StrOffset+StrLen(Loc)+Loc1
      }
      If FileName
      {
         Num++
         %Files%%Num% := FileName, %Size%%Num% := Bytes1
      }
   }
}


Edit: I think there are a few bugs in mine. Ill fix them later when I get time if you wanna use it.


Last edited by tic on December 31st, 2007, 1:12 am, edited 2 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 30th, 2007, 7:58 pm 
Offline
User avatar

Joined: August 11th, 2004, 1:47 am
Posts: 5347
Location: UK
This is really awesome, and the fact that you've gone stdlib compliant pleases me even more. Keep up the great work dude.

Example:

Code:
tor = E:\Downloads\Torrents\Fedora-8-dvd-i386.torrent
MsgBox, % Torrent_GetFiles(tor)

/* gives:

      Fedora-8-dvd-i386\Fedora-8-i386-DVD.iso
      Fedora-8-dvd-i386\Fedora-8-i386-rescuecd.iso
      Fedora-8-dvd-i386\SHA1SUM

_________________
GitHubScriptsIronAHK Contact by email not private message.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 31st, 2007, 7:26 am 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
Thanks for the comments Titan, and the example code :)

I'll give your version a test tic and update mine as necessary. I want to make sure to keep it stdlib compliant so I can put my upcoming torrent functions with it, and I want to make sure to keep it simple, but the regex and many aspects of your code seem like they could be superior to mine. Thanks for posting your version! It'll definitely help when creating the other Torrent_ functions I'm working on as well.

Note that if anyone needs to get any other random data out of Torrent dictionaries, my Bencode_GetValue function here should do the trick. It can actually get Files (partially broken), comments, announce info, any any other specific data, but I still plan on wrapping that in actual Torrent_ functions and keeping two separate libraries so that the torrent functions can be completely straight-forward (eg. bencode decoding behind the scenes).

Moving beyond this single Torrent_GetFiles function, however, the Torrent library is going to start to require my Bencode library soon (once I expand that enough to where it can handle all the bencode operations needed of course).

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 31st, 2007, 1:55 pm 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
Quote:
I want to make sure to keep it stdlib compliant so I can put my upcoming torrent functions with it, and I want to make sure to keep it simple


I went for simplicity when i wrote it. I didnt try to fit with the stdlib (tbh i dont even know what is required to do that) but tried to make it similar to the actual ahk functions as it returns the number of parameters in Var0 and then each one can be referenced with Var1, Var2.... without the need for stringsplits on return. I just like to have the function handle everything rather than making someone do things before or after. I would actually be interested to know what makes a function stdlib compliant though, as i hear it a lot but never really worry about what it means :)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 31st, 2007, 2:11 pm 
Offline
User avatar

Joined: August 11th, 2004, 1:47 am
Posts: 5347
Location: UK
tic wrote:
I would actually be interested to know what makes a function stdlib compliant
First is making sure your script is meets AutoHotkeys requirements and second is to document your work in a plain text format, preferably using the Natural Docs syntax as it works with majikinetors setup and XN-Docs.

_________________
GitHubScriptsIronAHK Contact by email not private message.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 31st, 2007, 3:09 pm 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
Thanks Titan.

I made a couple of changes to my previous code and made the gui a bit nicer. I added a quick option as demonstrated to allow the function to receive a url as its input. its a shame that urldownloadtofile is still so limited (should definitely be in the top 5 needed changes for the next verison of ahk)

Code:
#SingleInstance Force

Space := "                                                     "
KB := 1024**1, MB := 1024**2, GB := 1024**3

Gui, 1: Add, Button, x10 y10 w75 r1 -Multi -Wrap gBrowse Default, &Browse
Gui, 1: Add, Edit, x+10 y10 w430 r1 -Multi -Wrap vEdit, http://isohunt.com/download/29934468/pure+pwnage
Gui, 1: Add, Button, x+10 y10 w75 r1 -Multi -Wrap gRead Default, &Read
Gui, 1: Add, ListView, x10 y+20 w600 h400, File %Space%%Space%%Space%|Size
Gui, 1: Add, Text, x10 y470 w200 r1 -Multi -Wrap, Announce URLs:
Gui, 1: Add, Edit, x10 y+10 w295 h100 vAnnounce
Gui, 1: Add, Text, x+10 y470 w200 r1 -Multi -Wrap, Comments:
Gui, 1: Add, Edit, x315 y+10 w295 h100 vComment
Gui, 1: Show, AutoSize
Return

Browse:
Gui, 1: +OwnDialogs
FileSelectFile, Torrent,,, Select Torrent to read, Torrents (*.torrent)
If ErrorLevel
Return
GuiControl,, Edit, %Torrent%
Return

Read:
AnnounceURL := ""
Gui, 1: Submit, NoHide
TorrentRead(Edit, "Data", "Size", "Announce", "Comment")
LV_Delete()
Loop, %Data0%
{
   If (Size%A_Index% < KB)
   LV_Add("", Data%A_Index%, Size%A_Index% " Bytes")
   Else If (Size%A_Index% >= KB) && (Size%A_Index% < MB)
   LV_Add("", Data%A_Index%, Size%A_Index%//1024 " KB")
   Else If (Size%A_Index% >= MB) && (Size%A_Index% < GB)
   LV_Add("", Data%A_Index%, Round(Size%A_Index%/(1024*1024), 1) " MB")
   Else If (Size%A_Index% >= GB)
   LV_Add("", Data%A_Index%, Round(Size%A_Index%/(1024*1024*1024), 1) " GB")
}
Loop, %Announce0%
AnnounceURL .= Announce%A_Index% "`n"
GuiControl,, Announce, % SubStr(AnnounceURL, 1, StrLen(AnnounceURL)-1)
GuiControl,, Comment, %Comment%
Return

;#######################################################################################
; Torrent: Path to torrent
; Files: Variable to put names of torrent files into. Variable0 contains number of files
; Size: Variable to put sizes of files into. Variable0 contains number of files, same as above
; Announce: Variable to put announce url into. Variable0 contains number of urls
; TorrentComment: Variable to put the comment for the torrent into

TorrentRead(Torrent, Files="", Size="", Announce="", TorrentComment="")
{    
   Local Data,Name,Name1,Name2,StrOffset,FileName,Num,Loc,Loc1,URL,URL1,Tracker,RetComment,RetComment1,Bytes,Bytes1
   
   If Torrent contains http,url,www
   {
      UrlDownloadToFile, %Torrent%, Torrent.torrent
      FileRead, Data, Torrent.torrent
      FileDelete,  Torrent.torrent
   }
   Else
   FileRead, Data, %Torrent%
   
   RegExMatch(Data, "4:name([0-9]+):(.+?):", Name)
   Name := Substr(Name2, 1, Name1)
   
   If Announce
   {
      StrOffset := 1
      Loop
      {
         If A_Index = 1
         StrOffset := RegExMatch(Data, "announce([0-9]+):", URL, StrOffset)
         Else
         StrOffset := RegExMatch(Data, "([0-9]+):", URL, StrOffset)
         Tracker := SubStr(Data, StrOffset+StrLen(URL), URL1)
         If Tracker contains http,udp
         {
            Num++
            %Announce%%Num% := Tracker, StrOffset := StrOffset+StrLen(URL)+URL1
         }
         Else If (Tracker = "announce-list")
         StrOffset := StrOffset+StrLen(URL)+URL1
         Else
         Break   
      }
      %Announce%0 := Num
   }
   
   If TorrentComment
   StrOffset := RegExMatch(Data, "comment([0-9]+):", RetComment), %TorrentComment% := SubStr(Data, StrOffset+StrLen(RetComment), RetComment1)
   
   StrOffset := 1, Num := ""
   Loop
   {
      If Size
      RegExMatch(Data, "6:lengthi([0-9]+)e", Bytes, StrOffset)
      StrOffset := InStr(Data, "4:path", 0, StrOffset) + 6
      If StrOffset = 6
      {
         If A_Index = 1
         {
            %Files%0 := 1, %Files%1 := Name
            If Size
            %Size%0 := %Files%0, %Size%1 := Bytes1
         }
         Else
         {
            %Files%0 := Num
            If Size
            %Size%0 := %Files%0
         }
         Return
      }

      FileName := Name
      Loop
      {
         If (SubStr(Data, StrOffset, 1) = "e")
         Break   
         StrOffset := RegExMatch(Data, "([0-9]+):", Loc, StrOffset)
         FileName .= "\" SubStr(Data, StrOffset+StrLen(Loc), Loc1), StrOffset := StrOffset+StrLen(Loc)+Loc1
      }
      If FileName
      {
         Num++
         %Files%%Num% := FileName, %Size%%Num% := Bytes1
      }
   }
}


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 1st, 2008, 5:25 am 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
I have posted version 0.3 and renamed this topic to encapsulate the whole Torrent library as it is created.

I have added the Torrent_Load function, which must now be called before any other torrent functions in order to increase speed and minimize memory usage.

Use it like:
Code:
Torrent_Load(var, "C:\files\file.torrent")


Then refer to the newly created variable in the other functions (currently only one other function). This will dramatically increase speed if you need to use more than one Torrent function (a moot point so far)

I have also added a new parameter to Torrent_Getfiles, _ListDir. With _ListDir true (default), the container directory will be included before each filename in the list. If false, the container directory will not be listed. On a related note, ErrorLevel is now also set to the container directory for multi-file torrents to avoid making another call to get that later.

The other major change in this update is that the library now requires my Bencode library.

It is currently used to load the file, and will also be used to retrieve much of the data from the file in coming functions. It's only natural that the torrent library uses external functions to encode/decode data to/from the torrent files.

I have not yet incorporated any of tic's code into the functions. I do have plans to do this, as well as add some new functions for additional capability, for the next version.

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 1st, 2008, 6:46 pm 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
I hope you dont mind but I think I should branch off and post some of the functions that I'm writing as then I can have control of how it gets implemented. I am going to write a few examples such as an rss reader for torrents and maybe a slow running single thread torrent search program.

I dont really like the direction of first loading the torrent using a function and then running the function to get the values, which in turn needs another function, and also you parse all the data and then parse it again at the end which I think is wasteful, and then it returns the names in line separated format, meaning they must be parsed a third time when returned. If you look at the code I gave, you can see that the data is only parsed once.

Im not having a go, Im just trying to point out some ways you could make it better :)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 1st, 2008, 6:54 pm 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
Go for it, you can do what you'd like with your code. I hope you don't mind if I take a few pointers from it still however.

For one thing, I only process the torrent file once, when it is loaded, and then I use ByRef vars to work with it, meaning it points to the same place in memory each time.

The reason I do this is so that I can have several Torrent functions which work on the same torrent file, without having to load the file for every function.

It wouldn't be very wise to specify the full torrent path in every call to a Torrent function, then have the script load and search the file anew each time.

The only data I parse twice is the list of files in the torrent, which is ONLY if you want the container folder prepended and ONLY for multi-file torrents.

Since this does everything that I need in SteamLab for the moment, and nobody has pointed out any other uses so far, I haven't taken the time to rewrite the whole function or add additional functionality yet. It's nothing against your code, it's probably superior to mine and I plan to greatly enhance the speed and commands used in future releases.

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 1st, 2008, 7:09 pm 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
I see the regex commands, which could shorten my code slightly. But I don't really see where I've gone terribly wrong with my code. Could you point out some instances where your code would be faster or work better than mine? I'd like to fix it if I've done something wrong, or there's a better (eg faster, or more beneficial) way to do it.

And I'm not talking about getting the other data out of your function, since that will be included in separate functions in my library. I just mean with reading the torrent and getting the files and name.

I also don't want to create a global array as I think that is messy and not quite as stdlib friendly, I just want to accept parameters and return a value. The caller can do what they'd like with the files after they're returned, or they can use my other future functions to work directly on the files without getting them into a list first.

GetFiles is only meant to get a list of the files. FOr that purpose, one method doesn't seem to be faster than the other in my tests so far.

I'll consider creating a global array for the files, but Loop, Parse works quite fast on all data I have returned from the function so far.

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 1st, 2008, 8:06 pm 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
Yes, from my tests also (doing 1000 loops and outputting time taken) the functions seem very similar speed, although with a couple of regexs the whole code becomes much shorter. The whole original code pretty much becomes:

Code:
FileRead, Data, %Torrent%
RegExMatch(Data, "4:name([0-9]+):(.+?):", Name)
Name := Substr(Name2, 1, Name1)
.....
FileName := Name
Loop
{
   If (SubStr(Data, StrOffset, 1) = "e")
   Break   
   StrOffset := RegExMatch(Data, "([0-9]+):", Loc, StrOffset)
   FileName .= "\" SubStr(Data, StrOffset+StrLen(Loc), Loc1), StrOffset := StrOffset+StrLen(Loc)+Loc1
}


Quote:
I also don't want to create a global array as I think that is messy and not quite as stdlib friendly


it may not be stdlib friendly, but i actually prefer it (obviously or i wouldnt have done it ;)) as it fits nicer with how all the other ahk commands work. you specify an output var, and it will create an array with var0 being the number in the array.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 1st, 2008, 8:23 pm 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
I've been thinking, and I may introduce an optional ArrayVar attribute to the GetFiles function.

That way, if you put a var there, a global array will be created based on the var. If you don't put anything there, an `n-separated list is returned.

That would be something of a compromise and would give my script at least the flexibility to conform to the way you, and probably many others, would prefer, while still allowing me the simplicity of a return value as desired :)

I do understand that the way you've done it conforms to it being an AHK command. However, since my Torrent library is designed for future use to be used as the basis for a torrent script, calling its functions many times and for various things, I think in the case of a Library it's better to separate them rather than combine them all into a single function. For your purpose, it may be better to keep them all together, however.

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 1st, 2008, 9:30 pm 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
I created an example of how the function could be used and posted it:

http://www.autohotkey.com/forum/viewtopic.php?p=169564

Thanks bmcclure


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 1st, 2008, 9:40 pm 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
Great work, Tic!

I've added a link to it at the end of the first post in this topic so some will hopefully cross over and check out your alternative as well.

Not to mention yours is much more full-featured than my little function thus far :)

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 29 posts ]  Go to page Previous  1, 2

All times are UTC [ DST ]


Who is online

Users browsing this forum: Exabot [Bot], Stigg and 18 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