This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
NullSchritt's profile picture

Creating a menu with changing content (HTTP)

Started by NullSchritt, 16 May 2013 - 03:21 AM
NullSchritt #1
Posted 16 May 2013 - 05:21 AM
Hello all, I have run into a small problem while writing my application. Basically what it does it gets a list of stargate names from my server (http://projectbuilder.info/fetch.php?cmd=page&ID=gatedirectory&buffer=0) and then what I want it to do next is create a selectable menu out of the list, so that if the user selects one and presses enter, the program would return the name they selected, and then it would ask the server what the address for that name is.

I'm only having problems making the list from the data, I understand all the http stuff fine. From the examples I have seen, it would appear that in order to make a menu as I have described, I would have to parse my list and return a script which indicates a separate condition for each selection, defining which item should be highlighted.

It seems to me that certainly there must be some way to do this dynamically with a loop, without pre-processing the list into a menu script?

Any help would be much appreciated! Thanks, loving this plugin.
Smiley43210 #2
Posted 16 May 2013 - 06:45 AM
You're able to edit the PHP right?
First off: Do you serve HTML tags to everyone? Or is it just if the user agent isn't Java? If the user agent isn't checked, I recommend that you do check first.
Example:
#In this example, $cont contains the content of the file as a whole, e.g. "North City|Nether|Spawn". It does not contain any HTML tags.
if (!stristr($_SERVER['HTTP_USER_AGENT'], "java")) {
  echo("<html><body><pre style='word-wrap: break-word; white-space: pre-wrap;'>".htmlspecialchars($cont)."</pre></body></html>");
} else {
  echo($cont);
}
What that does it check to see if the request is coming from java or not. Not foolproof, but I don't see why anyone would set their user agent to something containing "java". Anyways, if the request is coming from java, we can assume that it's ComputerCraft. And we don't spit out any pre or html tags. If it's a browser, we do.

Next, the menu. In this example, the output of the fetch.php page is "Spawn|Nether|North City Skylands"
-- //Obviously this would normally be set with http.get()
-- //For demonstration purposes, I hardcoded it
local out = "Spawn|Nether|North City Skylands"
local list = { } -- //This will hold individual strings
local link = { } -- //This will hold the click area for each label
local cursor = 1 -- //Keeping our position during the search

-- //There is probably a much faster and more efficient way to do this search
while string.find(out, "|") do
  table.insert(list, string.sub(out, cursor, string.find(out, "|") - 1))
  cursor = string.find(out, "|") + 1
end

-- //Since we only grab occurrences BEFORE the "|" character, we need to check if there is anything AFTER it (the last "|" only)
if #list > 0 then
  if string.sub(out, cursor) ~= "" then
	 table.insert(list, string.sub(out, cursor))
  end
end
 
-- And I got too tired to finish my example.
Yeah, sorry. If anyone else comes along before I finish tomorrow, great. It's 1:17 AM here, I better go to sleep.
NullSchritt #3
Posted 16 May 2013 - 08:43 PM
Currently the php script is editable, in fact, I wrote it, and what it does is it connects to a mysql database and prints the "NAME" column of the database, with a | between each name so that the string can be split into an array.


local request = http.get("http://smp.projectbuilder.info/fetch.php?cmd=page&ID=gatedirectory&buffer=0" )
local  out = request.readAll()

There is no html, in fact no headers at all sent, it's sent as plain text. (:
LBPHacker #4
Posted 17 May 2013 - 02:37 AM

local request = http.get("http://smp.projectbuilder.info/fetch.php?cmd=page&ID=gatedirectory&buffer=0" )
local  out = content.readAll()
You know that content is nil, right?
Smiley43210 #5
Posted 17 May 2013 - 06:51 PM
Currently the php script is editable, in fact, I wrote it, and what it does is it connects to a mysql database and prints the "NAME" column of the database, with a | between each name so that the string can be split into an array.


local request = http.get("http://smp.projectbuilder.info/fetch.php?cmd=page&ID=gatedirectory&buffer=0" )
local  out = content.readAll()

There is no html, in fact no headers at all sent, it's sent as plain text. (:
Well, then either your web host is very unique in that they automatically add <pre> tags in front of it, or my browser is doing that (It didn't do it on my site -_-/>). Anyways, for the menu creation. Starting back where I left off…

You might want to have another PHP page to get the address for each stargate. Perhaps use GET for that. Then, we can ask the server for the one that is selected. Example: getAddress.php?name=Nether outputs (address for the Nether stargate).
Not tested:
Spoiler
-- //Obviously this would normally be set with http.get()
-- //For demonstration purposes, I hardcoded it
local out = "Spawn|Nether|North City Skylands"
local list = { } -- //This will hold individual strings
local link = { } -- //This will hold the click area for each label
local cursor = 1 -- //Keeping our position during the search

-- //There is probably a much faster and more efficient way to do this search
while string.find(out, "|") do
  table.insert(list, string.sub(out, cursor, string.find(out, "|") - 1))
  cursor = string.find(out, "|") + 1
end

-- //Since we only grab occurrences BEFORE the "|" character, we need to check if there is anything AFTER it (the last "|" only)
if #list > 0 then
  if string.sub(out, cursor) ~= "" then
	 table.insert(list, string.sub(out, cursor))
  end
end
-- Some inefficient menu that I threw together
term.clear()
term.setCursorPos(1, 1)
for _, v in ipairs(list) do
print(v)
end

for e, p1 in ipairs(os.pullEvent("key")) do
if p1 == keys.up then
  local x, y = term.getCursorPos()
  if y > 2 and y <= #list then
   term.clearLine()
   term.setCursorPos(1, y)
   write(list[y])
   term.setCursorPos(1, y - 1)
   write("> "..list[y - 1])
elseif p1 == keys.down then
  local x, y = term.getCursorPos()
  if y < #list then
   term.clearLine()
   term.setCursorPos(1, y)
   write(list[y])
   term.setCursorPos(1, y + 1)
   write("> "..list[y + 1])
elseif p1 == keys.enter
   local x, y = term.getCursorPos()
   local request = http.get("") -- //Put URL here that gets the stargate addresses
   local out = request.readAll()
   term.clear()
   term.setCursorPos(1, 1)
   print("Stargate address for "..list[y]..":")
   print(out)
   break
end
NullSchritt #6
Posted 17 May 2013 - 07:31 PM

local request = http.get("http://smp.projectbuilder.info/fetch.php?cmd=page&ID=gatedirectory&buffer=0" )
local  out = content.readAll()
You know that content is nil, right?
Yes it was an error in my code, but I fixed it.
NullSchritt #7
Posted 17 May 2013 - 07:32 PM
Currently the php script is editable, in fact, I wrote it, and what it does is it connects to a mysql database and prints the "NAME" column of the database, with a | between each name so that the string can be split into an array.


local request = http.get("http://smp.projectbuilder.info/fetch.php?cmd=page&ID=gatedirectory&buffer=0" )
local  out = content.readAll()

There is no html, in fact no headers at all sent, it's sent as plain text. (:
Well, then either your web host is very unique in that they automatically add <pre> tags in front of it, or my browser is doing that (It didn't do it on my site -_-/>). Anyways, for the menu creation. Starting back where I left off…

You might want to have another PHP page to get the address for each stargate. Perhaps use GET for that. Then, we can ask the server for the one that is selected. Example: getAddress.php?name=Nether outputs (address for the Nether stargate).
Not tested:
Spoiler
-- //Obviously this would normally be set with http.get()
-- //For demonstration purposes, I hardcoded it
local out = "Spawn|Nether|North City Skylands"
local list = { } -- //This will hold individual strings
local link = { } -- //This will hold the click area for each label
local cursor = 1 -- //Keeping our position during the search

-- //There is probably a much faster and more efficient way to do this search
while string.find(out, "|") do
  table.insert(list, string.sub(out, cursor, string.find(out, "|") - 1))
  cursor = string.find(out, "|") + 1
end

-- //Since we only grab occurrences BEFORE the "|" character, we need to check if there is anything AFTER it (the last "|" only)
if #list > 0 then
  if string.sub(out, cursor) ~= "" then
	 table.insert(list, string.sub(out, cursor))
  end
end
-- Some inefficient menu that I threw together
term.clear()
term.setCursorPos(1, 1)
for _, v in ipairs(list) do
print(v)
end

for e, p1 in ipairs(os.pullEvent("key")) do
if p1 == keys.up then
  local x, y = term.getCursorPos()
  if y > 2 and y <= #list then
   term.clearLine()
   term.setCursorPos(1, y)
   write(list[y])
   term.setCursorPos(1, y - 1)
   write("> "..list[y - 1])
elseif p1 == keys.down then
  local x, y = term.getCursorPos()
  if y < #list then
   term.clearLine()
   term.setCursorPos(1, y)
   write(list[y])
   term.setCursorPos(1, y + 1)
   write("> "..list[y + 1])
elseif p1 == keys.enter
   local x, y = term.getCursorPos()
   local request = http.get("") -- //Put URL here that gets the stargate addresses
   local out = request.readAll()
   term.clear()
   term.setCursorPos(1, 1)
   print("Stargate address for "..list[y]..":")
   print(out)
   break
end
Thanks! (my host is myself, I run my own dedicated server for all my web services, I don't know why it's generating pre tags for you, it must be something to do with your browser, perhaps because the data is sent without headers, but it should be returned as plain text when retrieved by the system http.get)

I already have a separate page which takes a name, and then looks up the address for the gate which most closely matches the text provided(the current dialing program works on queries but I thought it would be neat to also add a directory).

http://smp.projectbu...algate&amp;name=sky

I will add this into my dialing program when I get home, and let you know how it goes. I do have one other question though, how would I add a static option at the top of the menu to "Enter Address Manually" so that users could connect to hidden gates?