So until (if) Garry adds resource.AddWorkshopCollection() I have a theory.
Bare with me, I'm a bit rusty with Lua, although I could achieve this in Java...
After looking at the HTML source of the webpage that has all the addons in my collection I saw that every line that has the link to an addon looks like this:
<a href="http://steamcommunity.com/sharedfiles/filedetails/?id=160250458"><div class="workshopItemTitle">Wiremod</div></a>
and only one other line contains:
<div class="workshopItemTitle">"
and it's above every other one.
So my idea is a function, it starts by getting the HTML of the collection (assuming it's public) and packing the source in to a string. Then a for loop, that uses each line in the string.
In the for loop is an if statement containing two conditions, the first being that it contains that code that's in every line that contains a link, the second being that it is NOT the first string given by the for loop.
So if it contains that piece of HTML, and it's not the first occurrence of that line, then it'll get added to an array containing all the links to the addons, plus some extra junk.
To remove the junk, and retrieve the links, or more importantly the ID from those lines in the array we have a second for loop.
In Lua, if I'm not wrong, there is a function that returns the first parameter with the second parameter taken away from it, also one that will take the first parameter and only return the firsts few amount of characters, depending on the amount specified by the second parameter.
So I've only been using Lua about a month now but here is an incomplete, mostly imaginary function that will do this.
[CODE]function AddWorkshopCollection(id)
local webSource = web.Retrieve("http://steamcommunity.com/sharedfiles/filedetails/?id="..id) --fake code to retrieve the HTML
local webLines = {} --creates an array called webLines
local occurrences = 0
for k,v in pairs(string.Split(webSource, "\n")) do --fake code to split our first string by every new line and use each split as v in the for loop (I forget the function to actually do this...)
if string.find(v, '<div class="workshopItemTitle">') and not occurrences == 0 then --basically a code so that if v contains "<div class="workshopItemTitle">" anywhere in it AND if it's not the first occurrence of it
webLines[occurrences - 1] = v--add v to webLines
end
occurrences = occurrences + 1
end
for k,v in pairs(webLines) do --for every line in the HTML that contains "<div class="workshopItemTitle">" except the first
resource.AddWorkshop( string.removeEverythingAfterThisCharacter(string.TakeAway(v, "<a href="http://steamcommunity.com/sharedfiles/filedetails/?id="), 9)) --for every line in the HTML that meets the the standards above, do resourse.AddWorkshop assuming there is a fake code (TakeAway) that will return the first parameter, without the second if it contains the second, and another function (removeEverythingAfterThisCharacter) that would return the first parameter, but cut it down to the amount of letters provided by the second parameter
end
end
[/CODE]
Perhaps instead we should ask for a serverside game.GetWorkshopCollectionIDs(), to return a table of workshop ids involved in the server's collection as defined by the +host_workshop_collection command line entry, or use a collection ID provided as an argument. This would make adding all of a collection very simple, and could have other uses.
That's a brilliant idea! I'm looking up string chopping features to see what I can come up with but found nothing too helpful yet
Because http.Post has a delay (to connect to the webpage), you can't just use this function and immediately try to use the table it generates. This is why I'm using a callback function.
[lua]
function util.GetWorkshopCollectionIDs(collectionid,callback)
if collectionid == nil || callback == nil then return end
http.Fetch(
"http://steamcommunity.com/sharedfiles/filedetails/?id="..collectionid,
function(source)
local source_ = string.Explode("<div class=\"workshopItem\">",source)
local t = {}
for k, v in pairs(source_) do
local source__ = string.Explode("\"><div",v)
local insert = string.Explode("id=",source__[1])[2]
table.insert(t,insert)
end
table.remove(t,1)
callback(t)
end,
function()
return false
end
)
end
[/lua]
Usage:
[lua]
util.GetWorkshopCollectionIDs(some_id_here,function(ids)
for k, v in pairs(ids) do
resource.AddWorkshop(v)
end
end)
[/lua]
Keep in mind that if valve changes anything about collection webpages, this may break.
[editline]14th August 2013[/editline]
The beauty here is that using this, server owners can manage not only server content, but client downloads as well without editing files; you only need to use steam to manage what is inside of your server's workshop collection.
pull request? :v:
I made this :v:
[code]function util.GetWorkshopCollectionIDs( iIndex, callback )
http.Fetch( "http://steamcommunity.com/sharedfiles/filedetails/?id=" .. iIndex, function( sHTML )
local indices = {};
local bStop = false;
local iCount = 0;
local iStart = 0;
repeat
local iSt, iEnd, sFound = string.find( sHTML, [[<div id="sharedfile_(.-)" class="collectionItem">]], iStart );
iCount = iCount + 1;
if ( isstring( sFound ) ) then
table.insert( indices, tonumber( sFound ) );
iStart = iEnd;
continue;
end
bStop = true;
until ( bStop || iCount > 1000 );
if ( callback && type( callback ) == "function" ) then
callback( indices );
end
end );
end
util.GetWorkshopCollectionIDs( 193189432, function( indices )
print( "Found: " );
PrintTable( indices );
end );[/code]
Not sure why you are removing from the string when string.find accepts a start position as an argument.
[code]function resource.AddWorkshopCollection( id )
http.Fetch( "http://steamcommunity.com/sharedfiles/filedetails/?id=" .. id, function( page )
for k in page:gmatch( [[<div id="sharedfile_(.-)" class="collectionItem">]] ) do
resource.AddWorkshop( k )
end
end )
end[/code]
Roughly three times as fast and a lot cleaner.
I didn't know string.find had a start position argument. Thanks for the boxes guys, I only made an effort to help. :dance:
[QUOTE=Kogitsune;42883000]Not sure why you are removing from the string when string.find accepts a start position as an argument.
[code]function resource.AddWorkshopCollection( id )
http.Fetch( "http://steamcommunity.com/sharefiles/filedetails/?id=" .. id, function( page )
for k in page:gmatch( [[<div id="sharedfile_(.-)" class="collectionItem">]] ) do
resource.AddWorkshop( k )
end
end )
end[/code]
Roughly three times as fast and a lot cleaner.[/QUOTE]
That Code Will not work because the d has been removed from shared, but its very useful nonetheless
[code]function resource.AddWorkshopCollection( id )
http.Fetch( "http://steamcommunity.com/sharedfiles/filedetails/?id=" .. id, function( page )
for k in page:gmatch( [[<div id="sharedfile_(.-)" class="collectionItem">]] ) do
resource.AddWorkshop( k )
end
end )
end[/code]
[url]http://facepunch.com/showthread.php?t=1325685[/url]
Look at that, it's my tool. All you do it put the collection link, click navigate, then click generate and you will have every item from that collection in their own resource.AddWorkshop
Example:
[img]http://puu.sh/5k8Sn.png[/img]
[QUOTE=Koolsami7;42884559][url]http://facepunch.com/showthread.php?t=1325685[/url]
Look at that, it's my tool. All you do it put the collection link, click navigate, then click generate and you will have every item from that collection in their own resource.AddWorkshop
Example:
[img]http://puu.sh/5k8Sn.png[/img][/QUOTE]
While your resource generator could also prove very useful, it requires the server owners/devs to do that every time they add a new item to the collection, this method does it automatically.
Sorry, you need to Log In to post a reply to this thread.