This commit is contained in:
lx
2026-07-06 14:01:11 -04:00
commit c4f97d729d
16468 changed files with 935321 additions and 0 deletions
@@ -0,0 +1,8 @@
{
"language": {
"mode": "nonstrict"
},
"lint": {
"ImplicitReturn": "fatal"
}
}
@@ -0,0 +1,19 @@
local CorePackages = game:GetService("CorePackages")
local HttpService = game:GetService("HttpService")
local Url = require(CorePackages.AppTempCommon.LuaApp.Http.Url)
return function(requestImpl, conversationId, universeId, decorators)
assert(requestImpl, "requestImpl is required")
assert(conversationId, "conversationId is required")
assert(universeId, "universeId is required")
local payload = HttpService:JSONEncode({
conversationId = conversationId,
universeId = universeId,
decorators = decorators
})
local url = string.format("%s/send-game-link-message", Url.CHAT_URL)
return requestImpl(url, "POST", { postBody = payload })
end
@@ -0,0 +1,16 @@
local CorePackages = game:GetService("CorePackages")
local HttpService = game:GetService("HttpService")
local Url = require(CorePackages.AppTempCommon.LuaApp.Http.Url)
return function(requestImpl, conversationId, messageText, decorators)
local payload = HttpService:JSONEncode({
conversationId = conversationId,
message = messageText,
decorators = decorators
})
local url = string.format("%s/send-message", Url.CHAT_URL)
return requestImpl(url, "POST", { postBody = payload })
end
@@ -0,0 +1,14 @@
local CorePackages = game:GetService("CorePackages")
local HttpService = game:GetService("HttpService")
local Url = require(CorePackages.AppTempCommon.LuaApp.Http.Url)
return function(requestImpl, userId, clientId)
local payload = HttpService:JSONEncode({
participantuserId = userId
})
local url = string.format("%s/start-one-to-one-conversation", Url.CHAT_URL)
return requestImpl(url, "POST", { postBody = payload })
end
@@ -0,0 +1,25 @@
local CorePackages = game:GetService("CorePackages")
local Url = require(CorePackages.AppTempCommon.LuaApp.Http.Url)
--[[
Docs: https://thumbnails.roblox.com/docs#!/Games/get_v1_games_icons
This resolves to
{
"data": [
{
"targetId": 0,
"state": "Error",
"imageUrl": "string"
}
]
}
]]
return function (requestImpl, universeIds, size)
local qs = Url:makeQueryString({
universeIds = table.concat(universeIds, ","),
format = "png",
size = size,
})
local url = string.format("%sv1/games/icons?%s", Url.THUMBNAILS_URL, qs)
return requestImpl(url, "GET")
end
@@ -0,0 +1,54 @@
--[[
*** DEPRECATED ***
TODO: removed this file after new thumbnail API is being in use without any flags
RELATED: GAMEDISC-27 GAMEDISC-126 FIntLuaAppPercentRollOutNewThumbnailsApiV3
]]
local CorePackages = game:GetService("CorePackages")
local Url = require(CorePackages.AppTempCommon.LuaApp.Http.Url)
--[[
This endpoint returns a promise that resolves to:
[
{
"final": true,
"url": "string",
"retryToken": "string",
"universeId": 0,
"placeId": 0
}, {...}, ...
]
]]
-- requestImpl - (function<promise<HttpResponse>>(url, requestMethod, options))
-- imageTokens - (array<long>) the placeIds of the places you want to get thumbnails for
-- height - (int) the height of the asset to render
-- width - (int) the width of the asset to render
return function(requestImpl, imageTokens, height, width)
local args = {}
if height then
table.insert(args, string.format("height=%d", height))
end
if width then
table.insert(args, string.format("width=%d", width))
end
-- append all of the thumbnail tokens
local totalTokens = 0
for _, value in pairs(imageTokens) do
totalTokens = totalTokens + 1
table.insert(args, string.format("imageTokens=%s", value))
end
if totalTokens == 0 then
error("cannot fetch thumbnails without tokens")
end
-- construct the url
local url = string.format("%sv1/games/game-thumbnails?%s", Url.GAME_URL, table.concat(args, "&"))
-- return a promise of the result listed above
return requestImpl(url, "GET")
end
@@ -0,0 +1,33 @@
local CorePackages = game:GetService("CorePackages")
local Url = require(CorePackages.AppTempCommon.LuaApp.Http.Url)
--[[
This endpoint returns games' information with a batches of place ids
Doc: https://games.roblox.com/docs#!/Games/get_v1_games_multiget_place_details
{
"placeId": 0,
"name": "string",
"description": "string",
"url": "string",
"builder": "string",
"builderId": 0,
"isPlayable": true,
"reasonProhibited": "string",
"universeId": 0,
"universeRootPlaceId": 0,
"price": 0,
"imageToken": "string"
}
]]--
return function(requestImpl, placeIds)
local argTable = {
placeIds = placeIds,
}
local args = Url:makeQueryString(argTable)
local url = string.format("%s/v1/games/multiget-place-details?%s", Url.GAME_URL, args)
return requestImpl(url, "GET")
end
@@ -0,0 +1,17 @@
local CorePackages = game:GetService("CorePackages")
local Url = require(CorePackages.AppTempCommon.LuaApp.Http.Url)
return function(requestImpl, placeIds)
local argTable = {
placeIds = placeIds,
}
-- construct the url
local args = Url:makeQueryString(argTable)
local url = string.format("%s/v1/games/multiget-place-details?%s",
Url.GAME_URL, args
)
return requestImpl(url, "GET")
end
@@ -0,0 +1,39 @@
local CorePackages = game:GetService("CorePackages")
local Url = require(CorePackages.AppTempCommon.LuaApp.Http.Url)
--[[
Documentation of endpoint:
https://thumbnails.roblox.com/docs#!/Avatar/get_v1_users_avatar
input:
userIds
thumbnailSize
output:
[
{
"targetId": number,
"state": string,
"imageUrl": string,
},
]
]]
local MAX_USER_IDS = 100
return function (networkImpl, userIds, thumbnailSize)
assert(type(userIds) == "table", "ThumbnailsGetAvatar expects userIds to be a table")
if #userIds == 0 or #userIds > MAX_USER_IDS then
error(string.format("ThumbnailsGetAvatar request expects userIds count between 1-%d", MAX_USER_IDS))
end
local queryString = Url:makeQueryString({
userIds = table.concat(userIds, ","),
size = thumbnailSize,
format = "png",
})
local url = string.format("%sv1/users/avatar?%s", Url.THUMBNAILS_URL, queryString)
return networkImpl(url, "GET")
end
@@ -0,0 +1,39 @@
local CorePackages = game:GetService("CorePackages")
local Url = require(CorePackages.AppTempCommon.LuaApp.Http.Url)
--[[
Documentation of endpoint:
https://thumbnails.roblox.com/docs#!/Avatar/get_v1_users_avatar_headshot
input:
userIds
thumbnailSize
output:
[
{
"targetId": number,
"state": string,
"imageUrl": string,
},
]
]]
local MAX_USER_IDS = 100
return function (networkImpl, userIds, thumbnailSize)
assert(type(userIds) == "table", "ThumbnailsGetAvatarHeadshot expects userIds to be a table")
if #userIds == 0 or #userIds > MAX_USER_IDS then
error(string.format("ThumbnailsGetAvatarHeadshot request expects userIds count between 1-%d", MAX_USER_IDS))
end
local queryString = Url:makeQueryString({
userIds = table.concat(userIds, ","),
size = thumbnailSize,
format = "png",
})
local url = string.format("%sv1/users/avatar-headshot?%s", Url.THUMBNAILS_URL, queryString)
return networkImpl(url, "GET")
end
@@ -0,0 +1,31 @@
local CorePackages = game:GetService("CorePackages")
local Players = game:GetService("Players")
local Url = require(CorePackages.AppTempCommon.LuaApp.Http.Url)
local isNewFriendsEndpointsEnabled = require(CorePackages.AppTempCommon.LuaChat.Flags.isNewFriendsEndpointsEnabled)
--[[
This endpoint returns a promise that resolves to:
[
{
"success:" true,
"count": "0"
},
]
]]--
-- requestImpl - (function<promise<HttpResponse>>(url, requestMethod, options))
return function(requestImpl)
local url = string.format("%s/user/get-friendship-count?%s",
Url.API_URL, tostring(Players.LocalPlayer.UserId)
)
if isNewFriendsEndpointsEnabled() then
url = string.format("%s/my/friends/count", Url.FRIEND_URL)
end
return requestImpl(url, "GET")
end
@@ -0,0 +1,10 @@
local CorePackages = game:GetService("CorePackages")
local Url = require(CorePackages.AppTempCommon.LuaApp.Http.Url)
return function(requestImpl, userId)
local url = string.format("%s/users/%s/friends",
Url.FRIEND_URL, userId
)
return requestImpl(url, "GET")
end
@@ -0,0 +1,25 @@
local CorePackages = game:GetService("CorePackages")
local HttpService = game:GetService("HttpService")
local Url = require(CorePackages.AppTempCommon.LuaApp.Http.Url)
-- Endpoint documented here:
-- https://presence.roblox.com/docs
return function(requestImpl, userIds)
local userIdsToNumber = {}
for _, id in pairs(userIds) do
local idToNumber = tonumber(id)
if idToNumber then
table.insert(userIdsToNumber, idToNumber)
end
end
local payload = HttpService:JSONEncode({
userIds = userIdsToNumber,
})
local url = string.format("%s/presence/users", Url.PRESENCE_URL)
return requestImpl(url, "POST", { postBody = payload })
end
@@ -0,0 +1,48 @@
local CorePackages = game:GetService("CorePackages")
local Players = game:GetService("Players")
local Promise = require(CorePackages.AppTempCommon.LuaApp.Promise)
local THUMBNAIL_TYPE_BY_NAME = {
AvatarThumbnail = Enum.ThumbnailType.AvatarThumbnail,
HeadShot = Enum.ThumbnailType.HeadShot,
}
local THUMBNAIL_SIZE_BY_NAME = {
Size48x48 = Enum.ThumbnailSize.Size48x48,
Size60x60 = Enum.ThumbnailSize.Size60x60,
Size100x100 = Enum.ThumbnailSize.Size100x100,
Size150x150 = Enum.ThumbnailSize.Size150x150,
Size352x352 = Enum.ThumbnailSize.Size352x352
}
return function(userId, thumbnailType, thumbnailSize)
return Promise.new(function(resolve, reject)
--Async methods will yield the thread
spawn(function()
local result = {success = false}
local success, message = pcall(function()
local image, isFinal = Players:GetUserThumbnailAsync(
tonumber(userId), THUMBNAIL_TYPE_BY_NAME[thumbnailType], THUMBNAIL_SIZE_BY_NAME[thumbnailSize]
)
result = {
success = true,
id = userId,
thumbnailType = thumbnailType,
thumbnailSize = thumbnailSize,
image = isFinal and image or nil,
isFinal = isFinal,
}
end)
if success then
resolve(result)
else
result.message = message
reject(result)
end
end)
end)
end
@@ -0,0 +1,181 @@
--[[
Url Constructor
Provides a single location for base urls.
]]--
local ContentProvider = game:GetService("ContentProvider")
local FFlagLuaFixEconomyCreatorStatsUrl = game:DefineFastFlag("LuaFixEconomyCreatorStatsUrl", false)
-- helper functions
local function parseBaseUrlInformation()
-- get the current base url from the current configuration
local baseUrl = ContentProvider.BaseUrl
-- keep a copy of the base url (https://www.roblox.com/)
-- append a trailing slash if there isn't one
if baseUrl:sub(#baseUrl) ~= "/" then
baseUrl = baseUrl .. "/"
end
-- parse out scheme (http, https)
local _, schemeEnd = baseUrl:find("://")
-- parse out the prefix (www, kyle, ying, etc.)
local prefixIndex, prefixEnd = baseUrl:find("%.", schemeEnd + 1)
local basePrefix = baseUrl:sub(schemeEnd + 1, prefixIndex - 1)
-- parse out the domain (roblox.com/, sitetest1.robloxlabs.com/, etc.)
local baseDomain = baseUrl:sub(prefixEnd + 1)
return baseUrl, basePrefix, baseDomain
end
local function preventTableModification(aTable, key, value)
error("Attempt to modify read-only table")
end
local function createReadOnlyTable(aTable)
return setmetatable({}, {
__index = aTable,
__newindex = preventTableModification,
__metatable = false
});
end
-- url construction building blocks
local _baseUrl, _basePrefix, _baseDomain = parseBaseUrlInformation()
-- construct urls once
local _baseApiUrl = string.format("https://api.%s", _baseDomain)
local _baseApisUrl = string.format("https://apis.%s", _baseDomain)
local _baseAuthUrl = string.format("https://auth.%s", _baseDomain)
local _baseAccountSettingsUrl = string.format("https://accountsettings.%s", _baseDomain)
local _baseAvatarUrl = string.format("https://avatar.%s", _baseDomain)
local _baseCatalogUrl = string.format("https://catalog.%s", _baseDomain)
local _baseInventoryUrl = string.format("https://inventory.%s", _baseDomain)
local _baseChatUrl = string.format("https://chat.%sv2", _baseDomain)
local _baseFriendUrl = string.format("https://friends.%sv1", _baseDomain)
local _baseGameAssetUrl = string.format("https://assetgame.%s", _baseDomain)
local _baseGamesUrl = string.format("https://games.%s", _baseDomain)
local _baseGroupsUrl = string.format("https://groups.%s", _baseDomain)
local _baseNotificationUrl = string.format("https://notifications.%s", _baseDomain)
local _basePresenceUrl = string.format("https://presence.%sv1", _baseDomain)
local _baseRealtimeUrl = string.format("https://realtime.%s", _baseDomain)
local _baseWebUrl = string.format("https://web.%s", _baseDomain)
local _baseWwwUrl = string.format("https://www.%s", _baseDomain)
local _baseAdsUrl = string.format("https://ads.%s", _baseDomain)
local _baseFollowingsUrl = string.format("https://followings.%s", _baseDomain)
local _baseEconomyUrl = string.format("https://economy.%s", _baseDomain)
local _baseThumbnailsUrl = string.format("https://thumbnails.%s", _baseDomain)
local _baseAccountSettings = string.format("https://accountsettings.%s", _baseDomain)
local _basePremiumFeatures = string.format("https://premiumfeatures.%s", _baseDomain)
local _baseLocale = string.format("https://locale.%s", _baseDomain)
local _baseBadgesUrl = string.format("https://badges.%s", _baseDomain)
local _baseMetricsUrl = string.format("https://metrics.%sv1", _baseDomain)
local _baseApisRcsUrl = string.format("https://apis.rcs.%s", _baseDomain)
local _baseDiscussionsUrl = string.format("https://discussions.%s", _baseDomain)
local _baseContactsUrl = string.format("https://contacts.%s", _baseDomain)
local _baseSearchUrl = string.format("https://search.%s", _baseDomain)
local _baseStaticUrl = string.format("https://static.%s", _baseDomain)
local _baseGameSearchUITreatments = string.format("https://gamesearchuitreatments.api.%s", _baseDomain)
local _baseEconomyCreatorStats = FFlagLuaFixEconomyCreatorStatsUrl
and string.format("https://economycreatorstats.%s", _baseDomain)
or string.format("https://economycreatorstats.api.%s", _baseDomain)
local _baseUrlSecure = string.gsub(_baseUrl, "http://", "https://")
-- public api
local Url = {
DOMAIN = _baseDomain,
PREFIX = _basePrefix,
BASE_URL = _baseUrl,
BASE_URL_SECURE = _baseUrlSecure,
API_URL = _baseApiUrl,
APIS_URL = _baseApisUrl,
AUTH_URL = _baseAuthUrl,
ACCOUNT_SETTINGS_URL = _baseAccountSettingsUrl,
AVATAR_URL = _baseAvatarUrl,
CATALOG_URL = _baseCatalogUrl,
INVENTORY_URL = _baseInventoryUrl,
GAME_URL = _baseGamesUrl,
GAME_ASSET_URL = _baseGameAssetUrl,
GROUPS_URL = _baseGroupsUrl,
CHAT_URL = _baseChatUrl,
FRIEND_URL = _baseFriendUrl,
PRESENCE_URL = _basePresenceUrl,
NOTIFICATION_URL = _baseNotificationUrl,
REALTIME_URL = _baseRealtimeUrl,
WEB_URL = _baseWebUrl,
WWW_URL = _baseWwwUrl,
ADS_URL = _baseAdsUrl,
SEARCH_URL = _baseSearchUrl,
GAME_SEARCH_UI_TREATMENTS = _baseGameSearchUITreatments,
FOLLOWINGS_URL = _baseFollowingsUrl,
ECONOMY_URL = _baseEconomyUrl,
THUMBNAILS_URL = _baseThumbnailsUrl,
BADGES_URL = _baseBadgesUrl,
ACCOUNT_SETTINGS = _baseAccountSettings,
PREMIUM_FEATURES = _basePremiumFeatures,
LOCALE = _baseLocale,
METRICS_URL = _baseMetricsUrl,
APIS_RCS_URL = _baseApisRcsUrl,
DISCUSSIONS_URL = _baseDiscussionsUrl,
CONTACTS_URL = _baseContactsUrl,
STATIC_URL = _baseStaticUrl,
BLOG_URL = "https://blog.roblox.com/",
CORP_URL = "https://corp.roblox.com/",
ECNOMY_CREATOR_STATS = _baseEconomyCreatorStats,
}
function Url:getUserProfileUrl(userId)
return string.format("%susers/%s/profile", self.BASE_URL, userId)
end
function Url:getUserFriendsUrl(userId)
return string.format("%susers/%s/friends", self.BASE_URL, userId)
end
function Url:getUserInventoryUrl(userId)
return string.format("%susers/%s/inventory", self.BASE_URL, userId)
end
function Url:getPlaceDefaultThumbnailUrl(placeId, width, height)
return string.format(
"%sThumbs/Asset.ashx?width=%d&height=%d&assetId=%s&ignorePlaceMediaItems=true",
self.BASE_URL,
width,
height,
tostring(placeId))
end
function Url:isVanitySite()
return self.PREFIX ~= "www"
end
-- data - (table<string, string>) a table of key/value pairs to format
function Url:makeQueryString(data)
--NOTE - This function can be used to create a query string of parameters
-- at the end of url query, or create a application/form-url-encoded post body string
local params = {}
-- NOTE - Arrays are handled, but generally data is expected to be flat.
for key, value in pairs(data) do
if value ~= nil then --for optional params
if type(value) == "table" then
for i = 1, #value do
table.insert(params, key .. "=" .. value[i])
end
else
table.insert(params, key .. "=" .. tostring(value))
end
end
end
return table.concat(params, "&")
end
-- prevent anyone from modifying this table:
Url = createReadOnlyTable(Url)
return Url
@@ -0,0 +1,12 @@
return function()
local ContentProvider = game:GetService("ContentProvider")
local Url = require(script.Parent.Url)
it("The base url has not been changed for debugging", function()
local baseUrl = ContentProvider.BaseUrl
expect(baseUrl).to.equal(Url.BASE_URL)
end)
end