109 lines
3.8 KiB
Plaintext
109 lines
3.8 KiB
Plaintext
'
|
|
' Task used to scan the network and find jellyfin servers that are broadcasting over the SSDP protocol
|
|
'
|
|
|
|
sub init()
|
|
m.top.functionName = "execute"
|
|
end sub
|
|
|
|
sub execute()
|
|
m.top.content = GetServersViaSSDP()
|
|
end sub
|
|
|
|
function GetServersViaSSDP()
|
|
'brightscript can't escape characters in strings, so create a few vars here so we can use them in the strings below
|
|
Q = Chr(34)
|
|
CRLF = Chr(13) + Chr(10)
|
|
|
|
port = CreateObject("roMessagePort")
|
|
|
|
ssdpStr = ""
|
|
ssdpStr = ssdpStr + "M-SEARCH * HTTP/1.1" + CRLF
|
|
ssdpStr = ssdpStr + "HOST: 239.255.255.250:1900" + CRLF
|
|
ssdpStr = ssdpStr + "MAN: " + Q + "ssdp:discover" + Q + CRLF
|
|
ssdpStr = ssdpStr + "ST:urn:schemas-upnp-org:device:MediaServer:1" + CRLF
|
|
ssdpStr = ssdpStr + "MX: 2" + CRLF
|
|
ssdpStr = ssdpStr + CRLF
|
|
|
|
ssdpAddr = CreateObject("roSocketAddress")
|
|
ssdpAddr.SetAddress("239.255.255.250:1900")
|
|
|
|
ssdp = CreateObject("roDatagramSocket")
|
|
ssdp.SetMessagePort(port)
|
|
ssdp.SetSendToAddress(ssdpAddr)
|
|
ssdp.NotifyReadable(True)
|
|
ssdp.SendStr(ssdpStr)
|
|
|
|
locationUrls = {}
|
|
|
|
ut = CreateObject("roUrlTransfer")
|
|
ut.SetPort(port)
|
|
|
|
ts = CreateObject("roTimespan")
|
|
'wait for a maximum time
|
|
maxTimeMs = 2200
|
|
|
|
while True
|
|
elapsed = ts.TotalMilliseconds()
|
|
if elapsed >= maxTimeMs
|
|
exit while
|
|
end if
|
|
|
|
msg = Wait(maxTimeMs - elapsed, port)
|
|
|
|
if Type (msg) = "roSocketEvent" and msg.GetSocketId() = ssdp.GetId() and ssdp.IsReadable()
|
|
|
|
recvStr = ssdp.ReceiveStr(4096)
|
|
match = CreateObject("roRegex", "\r\nLocation:\s*(.*?)\s*\r\n", "i").Match(recvStr)
|
|
if match.Count() = 2
|
|
locationUrl = match[1]
|
|
if not locationUrls.DoesExist(locationUrl)
|
|
print "found network location: " + locationUrl
|
|
locationUrls.AddReplace(locationUrl, 0)
|
|
end if
|
|
end if
|
|
end if
|
|
end while
|
|
|
|
'download each of the discovered locations and see if any of them are named "Jellfin Server"
|
|
results = []
|
|
for each locationUrl in locationUrls
|
|
http = CreateObject("roUrlTransfer")
|
|
http.SetUrl(locationUrl)
|
|
responseText = http.GetToString()
|
|
xml = CreateObject("roXMLElement")
|
|
'if we successfully parsed the response, process it
|
|
if xml.Parse(responseText)
|
|
deviceNode = xml.GetNamedElementsCi("device")[0]
|
|
manufacturer = deviceNode.GetNamedElementsCi("manufacturer").GetText()
|
|
'only process jellyfin servers
|
|
if lcase(manufacturer) = "jellyfin"
|
|
'find the largest icon
|
|
width = 0
|
|
result = invalid
|
|
icons = deviceNode.GetNamedElementsCi("iconList")[0].GetNamedElementsCi("icon")
|
|
for each iconNode in icons
|
|
iconUrl = iconNode.GetNamedElementsCi("url").GetText()
|
|
baseUrl = invalid
|
|
match = CreateObject("roRegex", "(.*?)\/dlna\/", "i").Match(iconUrl)
|
|
if match.Count() = 2
|
|
baseUrl = match[1]
|
|
end if
|
|
loopResult = {
|
|
name: deviceNode.GetNamedElementsCi("friendlyName").GetText(),
|
|
baseUrl: baseUrl,
|
|
iconUrl: iconUrl,
|
|
iconWidth: iconNode.GetNamedElementsCi("width")[0].GetText().ToInt(),
|
|
iconHeight: iconNode.GetNamedElementsCi("height")[0].GetText().ToInt()
|
|
}
|
|
if baseUrl <> invalid and loopResult.iconWidth > width
|
|
result = loopResult
|
|
end if
|
|
end for
|
|
results.Push(result)
|
|
end if
|
|
end if
|
|
end for
|
|
return results
|
|
end function
|