2020-03-21 21:22:26 +00:00
|
|
|
function CreateServerGroup()
|
2021-07-09 20:08:32 +00:00
|
|
|
screen = CreateObject("roSGNode", "SetServerScreen")
|
2021-12-23 01:00:47 +00:00
|
|
|
screen.optionsAvailable = true
|
2021-10-10 02:04:37 +00:00
|
|
|
m.global.sceneManager.callFunc("pushScene", screen)
|
2021-07-09 20:08:32 +00:00
|
|
|
port = CreateObject("roMessagePort")
|
|
|
|
m.colors = {}
|
|
|
|
|
|
|
|
if get_setting("server") <> invalid
|
|
|
|
screen.serverUrl = get_setting("server")
|
2019-03-07 03:14:52 +00:00
|
|
|
end if
|
2021-07-09 20:08:32 +00:00
|
|
|
m.viewModel = {}
|
|
|
|
button = screen.findNode("submit")
|
|
|
|
button.observeField("buttonSelected", port)
|
2021-12-23 01:00:47 +00:00
|
|
|
'create delete saved server option
|
|
|
|
new_options = []
|
|
|
|
sidepanel = screen.findNode("options")
|
|
|
|
opt = CreateObject("roSGNode", "OptionsButton")
|
|
|
|
opt.title = tr("Delete Saved")
|
2021-12-24 04:08:43 +00:00
|
|
|
opt.id = "delete_saved"
|
2021-12-23 01:00:47 +00:00
|
|
|
opt.observeField("optionSelected", port)
|
|
|
|
new_options.push(opt)
|
|
|
|
sidepanel.options = new_options
|
|
|
|
sidepanel.observeField("closeSidePanel", port)
|
2021-12-24 04:08:43 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
screen.observeField("backPressed", port)
|
|
|
|
|
|
|
|
while true
|
|
|
|
msg = wait(0, port)
|
|
|
|
print type(msg), msg
|
|
|
|
if type(msg) = "roSGScreenEvent" and msg.isScreenClosed()
|
|
|
|
return "false"
|
|
|
|
else if isNodeEvent(msg, "backPressed")
|
|
|
|
return "backPressed"
|
2021-12-23 01:00:47 +00:00
|
|
|
else if isNodeEvent(msg, "closeSidePanel")
|
|
|
|
screen.setFocus(true)
|
|
|
|
serverPicker = screen.findNode("serverPicker")
|
|
|
|
serverPicker.setFocus(true)
|
2021-07-09 20:08:32 +00:00
|
|
|
else if type(msg) = "roSGNodeEvent"
|
|
|
|
node = msg.getNode()
|
|
|
|
if node = "submit"
|
|
|
|
serverUrl = standardize_jellyfin_url(screen.serverUrl)
|
|
|
|
'If this is a different server from what we know, reset username/password setting
|
|
|
|
if get_setting("server") <> serverUrl
|
|
|
|
set_setting("username", "")
|
|
|
|
set_setting("password", "")
|
|
|
|
end if
|
|
|
|
set_setting("server", serverUrl)
|
|
|
|
' Show Connecting to Server spinner
|
|
|
|
dialog = createObject("roSGNode", "ProgressDialog")
|
|
|
|
dialog.title = tr("Connecting to Server")
|
|
|
|
m.scene.dialog = dialog
|
|
|
|
|
|
|
|
serverInfoResult = ServerInfo()
|
|
|
|
|
|
|
|
dialog.close = true
|
|
|
|
|
|
|
|
if serverInfoResult = invalid
|
|
|
|
' Maybe don't unset setting, but offer as a prompt
|
|
|
|
' Server not found, is it online? New values / Retry
|
|
|
|
print "Server not found, is it online? New values / Retry"
|
|
|
|
screen.errorMessage = tr("Server not found, is it online?")
|
2021-12-30 01:00:13 +00:00
|
|
|
SignOut(false)
|
2021-07-09 20:08:32 +00:00
|
|
|
else if serverInfoResult.Error <> invalid and serverInfoResult.Error
|
|
|
|
' If server redirected received, update the URL
|
|
|
|
if serverInfoResult.UpdatedUrl <> invalid
|
|
|
|
serverUrl = serverInfoResult.UpdatedUrl
|
|
|
|
set_setting("server", serverUrl)
|
|
|
|
end if
|
|
|
|
' Display Error Message to user
|
|
|
|
message = tr("Error: ")
|
|
|
|
if serverInfoResult.ErrorCode <> invalid
|
|
|
|
message = message + "[" + serverInfoResult.ErrorCode.toStr() + "] "
|
|
|
|
end if
|
|
|
|
screen.errorMessage = message + tr(serverInfoResult.ErrorMessage)
|
2021-12-30 01:00:13 +00:00
|
|
|
SignOut(false)
|
2021-07-09 20:08:32 +00:00
|
|
|
else
|
|
|
|
screen.visible = false
|
2021-12-26 18:52:43 +00:00
|
|
|
if serverInfoResult.serverName <> invalid
|
|
|
|
return serverInfoResult.ServerName + " (Saved)"
|
|
|
|
else
|
|
|
|
return "Saved"
|
|
|
|
end if
|
2021-07-09 20:08:32 +00:00
|
|
|
end if
|
2021-12-23 01:00:47 +00:00
|
|
|
else if node = "delete_saved"
|
|
|
|
serverPicker = screen.findNode("serverPicker")
|
|
|
|
itemToDelete = serverPicker.content.getChild(serverPicker.itemFocused)
|
|
|
|
urlToDelete = itemToDelete.baseUrl
|
|
|
|
if urlToDelete <> invalid
|
|
|
|
DeleteFromServerList(urlToDelete)
|
|
|
|
serverPicker.content.removeChild(itemToDelete)
|
|
|
|
sidepanel.visible = false
|
|
|
|
serverPicker.setFocus(true)
|
2021-12-24 04:08:43 +00:00
|
|
|
end if
|
2021-07-09 20:08:32 +00:00
|
|
|
end if
|
|
|
|
end if
|
|
|
|
end while
|
2019-10-13 19:33:14 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
' Just hide it when done, in case we need to come back
|
|
|
|
screen.visible = false
|
|
|
|
return ""
|
2020-03-21 21:22:26 +00:00
|
|
|
end function
|
|
|
|
|
|
|
|
function CreateUserSelectGroup(users = [])
|
2021-07-09 20:08:32 +00:00
|
|
|
if users.count() = 0
|
2020-03-21 21:22:26 +00:00
|
|
|
return ""
|
|
|
|
end if
|
2021-07-09 20:08:32 +00:00
|
|
|
group = CreateObject("roSGNode", "UserSelect")
|
2021-10-10 02:04:37 +00:00
|
|
|
m.global.sceneManager.callFunc("pushScene", group)
|
2021-07-09 20:08:32 +00:00
|
|
|
port = CreateObject("roMessagePort")
|
|
|
|
|
|
|
|
group.itemContent = users
|
|
|
|
group.findNode("userRow").observeField("userSelected", port)
|
|
|
|
group.findNode("alternateOptions").observeField("itemSelected", port)
|
|
|
|
group.observeField("backPressed", port)
|
|
|
|
while true
|
|
|
|
msg = wait(0, port)
|
|
|
|
if type(msg) = "roSGScreenEvent" and msg.isScreenClosed()
|
|
|
|
group.visible = false
|
|
|
|
return -1
|
|
|
|
else if isNodeEvent(msg, "backPressed")
|
|
|
|
return "backPressed"
|
|
|
|
else if type(msg) = "roSGNodeEvent" and msg.getField() = "userSelected"
|
|
|
|
return msg.GetData()
|
|
|
|
else if type(msg) = "roSGNodeEvent" and msg.getField() = "itemSelected"
|
|
|
|
if msg.getData() = 0
|
|
|
|
return ""
|
|
|
|
end if
|
|
|
|
end if
|
|
|
|
end while
|
2020-03-21 21:22:26 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
' Just hide it when done, in case we need to come back
|
|
|
|
group.visible = false
|
|
|
|
return ""
|
2020-03-21 21:22:26 +00:00
|
|
|
end function
|
2019-03-07 03:14:52 +00:00
|
|
|
|
2020-03-21 21:22:26 +00:00
|
|
|
function CreateSigninGroup(user = "")
|
2021-07-09 20:08:32 +00:00
|
|
|
' Get and Save Jellyfin user login credentials
|
|
|
|
group = CreateObject("roSGNode", "ConfigScene")
|
2021-10-10 02:04:37 +00:00
|
|
|
m.global.sceneManager.callFunc("pushScene", group)
|
2021-07-09 20:08:32 +00:00
|
|
|
port = CreateObject("roMessagePort")
|
|
|
|
|
|
|
|
group.findNode("prompt").text = tr("Sign In")
|
|
|
|
|
2021-12-24 04:07:35 +00:00
|
|
|
'Load in any saved server data and see if we can just log them in...
|
|
|
|
server = get_setting("server")
|
2021-12-26 21:03:59 +00:00
|
|
|
if server <> invalid
|
|
|
|
server = LCase(server)'Saved server data is always lowercase
|
|
|
|
end if
|
2021-12-24 04:07:35 +00:00
|
|
|
saved = get_setting("saved_servers")
|
2021-12-24 04:08:43 +00:00
|
|
|
if saved <> invalid
|
2021-12-24 04:07:35 +00:00
|
|
|
savedServers = ParseJson(saved)
|
|
|
|
for each item in savedServers.serverList
|
2021-12-26 21:03:59 +00:00
|
|
|
if item.baseUrl = server and item.username <> invalid and item.password <> invalid
|
2021-12-24 04:07:35 +00:00
|
|
|
get_token(item.username, item.password)
|
|
|
|
if get_setting("active_user") <> invalid
|
|
|
|
return "true"
|
|
|
|
end if
|
|
|
|
end if
|
|
|
|
end for
|
|
|
|
end if
|
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
config = group.findNode("configOptions")
|
|
|
|
username_field = CreateObject("roSGNode", "ConfigData")
|
|
|
|
username_field.label = tr("Username")
|
|
|
|
username_field.field = "username"
|
|
|
|
username_field.type = "string"
|
|
|
|
if user = "" and get_setting("username") <> invalid
|
|
|
|
username_field.value = get_setting("username")
|
|
|
|
else
|
|
|
|
username_field.value = user
|
2019-03-07 03:14:52 +00:00
|
|
|
end if
|
2021-07-09 20:08:32 +00:00
|
|
|
password_field = CreateObject("roSGNode", "ConfigData")
|
|
|
|
password_field.label = tr("Password")
|
|
|
|
password_field.field = "password"
|
|
|
|
password_field.type = "password"
|
|
|
|
if get_setting("password") <> invalid
|
|
|
|
password_field.value = get_setting("password")
|
|
|
|
end if
|
2021-12-30 03:51:39 +00:00
|
|
|
' Add checkbox for saving credentials
|
|
|
|
checkbox = group.findNode("onOff")
|
|
|
|
items = CreateObject("roSGNode", "ContentNode")
|
|
|
|
items.role = "content"
|
|
|
|
saveCheckBox = CreateObject("roSGNode", "ContentNode")
|
|
|
|
saveCheckBox.title = tr("Save Credentials?")
|
|
|
|
items.appendChild(saveCheckBox)
|
|
|
|
checkbox.content = items
|
|
|
|
checkbox.checkedState = [true]
|
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
items = [username_field, password_field]
|
|
|
|
config.configItems = items
|
|
|
|
|
|
|
|
button = group.findNode("submit")
|
|
|
|
button.observeField("buttonSelected", port)
|
|
|
|
|
|
|
|
config = group.findNode("configOptions")
|
|
|
|
|
|
|
|
username = config.content.getChild(0)
|
|
|
|
password = config.content.getChild(1)
|
|
|
|
|
|
|
|
group.observeField("backPressed", port)
|
|
|
|
|
|
|
|
while true
|
|
|
|
msg = wait(0, port)
|
|
|
|
if type(msg) = "roSGScreenEvent" and msg.isScreenClosed()
|
|
|
|
group.visible = false
|
|
|
|
return "false"
|
|
|
|
else if isNodeEvent(msg, "backPressed")
|
|
|
|
group.unobserveField("backPressed")
|
|
|
|
group.backPressed = false
|
|
|
|
return "backPressed"
|
|
|
|
else if type(msg) = "roSGNodeEvent"
|
|
|
|
node = msg.getNode()
|
|
|
|
if node = "submit"
|
|
|
|
' Validate credentials
|
|
|
|
get_token(username.value, password.value)
|
|
|
|
if get_setting("active_user") <> invalid
|
|
|
|
set_setting("username", username.value)
|
|
|
|
set_setting("password", password.value)
|
2021-12-30 03:51:39 +00:00
|
|
|
if checkbox.checkedState[0] = true
|
|
|
|
'Update our saved server list, so next time the user can just click and go
|
|
|
|
UpdateSavedServerList()
|
|
|
|
end if
|
2021-07-09 20:08:32 +00:00
|
|
|
return "true"
|
|
|
|
end if
|
|
|
|
print "Login attempt failed..."
|
|
|
|
group.findNode("alert").text = tr("Login attempt failed.")
|
|
|
|
end if
|
|
|
|
end if
|
|
|
|
end while
|
2019-10-13 19:33:14 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
' Just hide it when done, in case we need to come back
|
|
|
|
group.visible = false
|
|
|
|
return ""
|
2020-03-21 21:22:26 +00:00
|
|
|
end function
|
2019-03-07 03:14:52 +00:00
|
|
|
|
2020-03-03 23:01:13 +00:00
|
|
|
function CreateHomeGroup()
|
2021-07-09 20:08:32 +00:00
|
|
|
' Main screen after logging in. Shows the user's libraries
|
|
|
|
group = CreateObject("roSGNode", "Home")
|
2021-09-14 02:03:32 +00:00
|
|
|
group.overhangTitle = tr("Home")
|
|
|
|
group.optionsAvailable = true
|
2021-07-09 20:08:32 +00:00
|
|
|
|
|
|
|
group.observeField("selectedItem", m.port)
|
|
|
|
group.observeField("quickPlayNode", m.port)
|
|
|
|
|
|
|
|
sidepanel = group.findNode("options")
|
|
|
|
sidepanel.observeField("closeSidePanel", m.port)
|
|
|
|
new_options = []
|
|
|
|
options_buttons = [
|
|
|
|
{ "title": "Search", "id": "goto_search" },
|
|
|
|
{ "title": "Change server", "id": "change_server" },
|
|
|
|
{ "title": "Sign out", "id": "sign_out" }
|
|
|
|
]
|
|
|
|
for each opt in options_buttons
|
|
|
|
o = CreateObject("roSGNode", "OptionsButton")
|
|
|
|
o.title = tr(opt.title)
|
|
|
|
o.id = opt.id
|
|
|
|
o.observeField("optionSelected", m.port)
|
|
|
|
new_options.push(o)
|
|
|
|
end for
|
|
|
|
|
2021-08-24 01:21:15 +00:00
|
|
|
' Add option for mpeg-2 playback
|
|
|
|
playMpeg2 = get_setting("playback.mpeg2")
|
|
|
|
if playMpeg2 = invalid
|
|
|
|
playMpeg2 = "true"
|
|
|
|
set_setting("playback.mpeg2", playMpeg2)
|
|
|
|
end if
|
|
|
|
o = CreateObject("roSGNode", "OptionsButton")
|
|
|
|
if playMpeg2 = "true"
|
|
|
|
o.title = tr("MPEG2 Support: On")
|
|
|
|
else
|
|
|
|
o.title = tr("MPEG2 Support: Off")
|
|
|
|
end if
|
|
|
|
o.id = "play_mpeg2"
|
|
|
|
o.observeField("optionSelected", m.port)
|
|
|
|
new_options.push(o)
|
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
' And a profile button
|
|
|
|
user_node = CreateObject("roSGNode", "OptionsData")
|
|
|
|
user_node.id = "active_user"
|
|
|
|
user_node.title = tr("Profile")
|
|
|
|
user_node.base_title = tr("Profile")
|
|
|
|
user_options = []
|
|
|
|
for each user in AvailableUsers()
|
|
|
|
user_options.push({ display: user.username + "@" + user.server, value: user.id })
|
|
|
|
end for
|
|
|
|
user_node.choices = user_options
|
|
|
|
user_node.value = get_setting("active_user")
|
|
|
|
new_options.push(user_node)
|
|
|
|
|
|
|
|
sidepanel.options = new_options
|
|
|
|
|
|
|
|
return group
|
2019-10-12 20:21:34 +00:00
|
|
|
end function
|
2019-03-07 03:14:52 +00:00
|
|
|
|
2019-10-13 19:33:14 +00:00
|
|
|
function CreateMovieDetailsGroup(movie)
|
2021-07-09 20:08:32 +00:00
|
|
|
group = CreateObject("roSGNode", "MovieDetails")
|
2021-09-14 02:03:32 +00:00
|
|
|
group.overhangTitle = movie.title
|
|
|
|
group.optionsAvailable = false
|
2021-10-16 20:03:10 +00:00
|
|
|
m.global.sceneManager.callFunc("pushScene", group)
|
2019-03-12 03:49:17 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
movie = ItemMetaData(movie.id)
|
|
|
|
group.itemContent = movie
|
2019-10-12 20:21:34 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
buttons = group.findNode("buttons")
|
|
|
|
for each b in buttons.getChildren(-1, 0)
|
|
|
|
b.observeField("buttonSelected", m.port)
|
|
|
|
end for
|
2019-03-17 23:07:57 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
return group
|
2019-10-12 20:21:34 +00:00
|
|
|
end function
|
2019-03-08 03:47:10 +00:00
|
|
|
|
2019-12-07 02:49:37 +00:00
|
|
|
function CreateSeriesDetailsGroup(series)
|
2021-07-09 20:08:32 +00:00
|
|
|
group = CreateObject("roSGNode", "TVShowDetails")
|
2021-09-14 02:03:32 +00:00
|
|
|
group.overhangTitle = series.title
|
|
|
|
group.optionsAvailable = false
|
2021-10-16 20:03:10 +00:00
|
|
|
m.global.sceneManager.callFunc("pushScene", group)
|
2019-03-11 01:24:50 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
group.itemContent = ItemMetaData(series.id)
|
|
|
|
group.seasonData = TVSeasons(series.id)
|
2019-03-31 03:15:53 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
group.observeField("seasonSelected", m.port)
|
2019-04-14 04:47:27 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
return group
|
2019-12-07 02:49:37 +00:00
|
|
|
end function
|
2019-04-14 04:47:27 +00:00
|
|
|
|
2019-12-07 02:49:37 +00:00
|
|
|
function CreateSeasonDetailsGroup(series, season)
|
2021-07-09 20:08:32 +00:00
|
|
|
group = CreateObject("roSGNode", "TVEpisodes")
|
2021-09-14 02:03:32 +00:00
|
|
|
group.overhangTitle = series.title + " " + season.title
|
|
|
|
group.optionsAvailable = false
|
2021-10-16 20:03:10 +00:00
|
|
|
m.global.sceneManager.callFunc("pushScene", group)
|
2019-04-14 04:47:27 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
group.seasonData = ItemMetaData(season.id).json
|
|
|
|
group.objects = TVEpisodes(series.id, season.id)
|
2019-04-14 04:47:27 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
group.observeField("episodeSelected", m.port)
|
|
|
|
group.observeField("quickPlayNode", m.port)
|
2019-04-14 04:47:27 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
return group
|
2019-12-07 02:49:37 +00:00
|
|
|
end function
|
2019-03-11 01:24:50 +00:00
|
|
|
|
2021-02-12 15:17:55 +00:00
|
|
|
function CreateItemGrid(libraryItem)
|
2021-07-09 20:08:32 +00:00
|
|
|
group = CreateObject("roSGNode", "ItemGrid")
|
|
|
|
group.parentItem = libraryItem
|
2021-09-14 02:03:32 +00:00
|
|
|
group.optionsAvailable = true
|
2021-07-09 20:08:32 +00:00
|
|
|
group.observeField("selectedItem", m.port)
|
|
|
|
return group
|
2020-05-31 13:46:33 +00:00
|
|
|
end function
|
|
|
|
|
2019-10-13 20:52:34 +00:00
|
|
|
function CreateSearchPage()
|
2021-07-09 20:08:32 +00:00
|
|
|
' Search + Results Page
|
|
|
|
group = CreateObject("roSGNode", "SearchResults")
|
2019-03-14 22:50:20 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
search = group.findNode("SearchBox")
|
|
|
|
search.observeField("search_value", m.port)
|
2019-03-14 22:50:20 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
options = group.findNode("SearchSelect")
|
|
|
|
options.observeField("itemSelected", m.port)
|
2019-03-14 22:50:20 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
return group
|
2019-10-13 20:52:34 +00:00
|
|
|
end function
|
2019-03-14 22:50:20 +00:00
|
|
|
|
2021-06-26 10:18:09 +00:00
|
|
|
sub CreateSidePanel(buttons, options)
|
2021-07-09 20:08:32 +00:00
|
|
|
group = CreateObject("roSGNode", "OptionsSlider")
|
|
|
|
group.buttons = buttons
|
|
|
|
group.options = options
|
2021-06-26 10:18:09 +00:00
|
|
|
end sub
|
2019-10-13 22:10:23 +00:00
|
|
|
|
2020-10-24 16:23:20 +00:00
|
|
|
function CreateVideoPlayerGroup(video_id, audio_stream_idx = 1)
|
2021-07-09 20:08:32 +00:00
|
|
|
' Video is Playing
|
|
|
|
video = VideoPlayer(video_id, audio_stream_idx)
|
|
|
|
if video = invalid then return invalid
|
|
|
|
video.observeField("selectSubtitlePressed", m.port)
|
|
|
|
video.observeField("state", m.port)
|
|
|
|
|
|
|
|
return video
|
2019-10-12 21:00:07 +00:00
|
|
|
end function
|
2021-12-24 04:07:35 +00:00
|
|
|
|
|
|
|
sub UpdateSavedServerList()
|
|
|
|
server = get_setting("server")
|
|
|
|
username = get_setting("username")
|
|
|
|
password = get_setting("password")
|
|
|
|
|
2021-12-24 04:08:43 +00:00
|
|
|
if server = invalid or username = invalid or password = invalid
|
2021-12-24 04:07:35 +00:00
|
|
|
return
|
|
|
|
end if
|
|
|
|
|
2021-12-26 21:03:59 +00:00
|
|
|
server = LCase(server)'Saved server data is always lowercase
|
|
|
|
|
2021-12-24 04:07:35 +00:00
|
|
|
saved = get_setting("saved_servers")
|
2021-12-26 20:41:32 +00:00
|
|
|
if saved <> invalid
|
2021-12-24 04:07:35 +00:00
|
|
|
savedServers = ParseJson(saved)
|
2021-12-26 20:25:58 +00:00
|
|
|
if savedServers.serverList <> invalid and savedServers.serverList.Count() > 0
|
|
|
|
newServers = { serverList: [] }
|
|
|
|
for each item in savedServers.serverList
|
2021-12-26 21:03:59 +00:00
|
|
|
if item.baseUrl = server
|
2021-12-26 20:25:58 +00:00
|
|
|
item.username = username
|
|
|
|
item.password = password
|
|
|
|
end if
|
|
|
|
newServers.serverList.Push(item)
|
|
|
|
end for
|
|
|
|
set_setting("saved_servers", FormatJson(newServers))
|
|
|
|
end if
|
2021-12-24 04:07:35 +00:00
|
|
|
end if
|
|
|
|
end sub
|