shitty reuploading

This commit is contained in:
Jill 2023-01-04 14:55:59 +03:00
parent 87342acee0
commit a0c97aa1f3
6 changed files with 84 additions and 5 deletions

View File

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/png" href="/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="/style.css" />
<title>Level Reupload</title>
</head>
<body>
<%- if error -%>
<div>Error while uploading: <%= error %></div><br />
<%- elsif level_id -%>
<div>Uploaded successfully! Level ID: <b><%= level_id %></b></div><br />
<%- end -%>
<form action="/tools/reupload" method="post">
ID: <input type="text" id="level_id" name="level_id" />
<input type="submit" value="Submit" />
</form>
<i>Currently only vanilla servers are supported</i>
</body>
</html>

View File

@ -27,8 +27,7 @@ CrystalGauntlet.endpoints["/uploadGJLevel21.php"] = ->(context : HTTP::Server::C
# todo: use 2.2 unlisted
# todo: https://github.com/Cvolton/GMDprivateServer/blob/master/incl/levels/uploadGJLevel.php#L53
extraString = params["extraString"]? || "29_29_29_40_29_29_29_29_29_29_29_29_29_29_29_29"
extraString = params["extraString"]? || Level::DEFAULT_EXTRA_STRING
original = (params["original"]? || "0").to_i32
if original == 0

View File

@ -3,7 +3,7 @@ module CrystalGauntlet::Clean
extend self
# for descriptions & similar
def clean_special(str)
def clean_special(str : String)
str.gsub(/[\0]/, "")
end

View File

@ -9,6 +9,14 @@ module CrystalGauntlet::Level
# security.webm
TEST_STRING = "H4sIAAAAAAAAC61Xy5HYIAxtyLuDJCTB5JQatgAKSAspPvxssC1lc8jBZngPhNAP-PVF6YASpWBhKlQkFoCCzAVwNNSbWD6gSIEQQtECBbj9UgklFfgNtcX6Uf2-mQ7udAhYxuhvRGRTRBszJvyTkLrfYusyBAE2Qe3_jSD-X4LEEXT8-gl0hNbwaGQ08ah_OaB1dECzSa35otx72P9DQid-xv4fbJ3dGzjCDzhAYzzwoHDQAbyA3IDYgdoD4qtL1HiQhmj91dU-ucIHNDbCTmIl8MB46JjZydxICHOq9rldlUAXLXlMCBVB7BMApjLViLtumDpdl8QmI8SuRlhMTEe1WRpLILbdxqnCpXGkKaQh0BCBU-xLzS7j4iuEXfM1oyr8IW3bH7TPPjcg-_Ktr6dFth0MkYNRWDuoqAZjfMPJwcWTPyXt8gdOb7zvWofzaNipxcnYdO5AMzoE2UyJHUm6mWpCp602u5xTL8NAyPaOANAj2COSQyB4RPQIfahJjkNqAHuE5ZJOGDvGsK_ysFnEhzLRs0D0LMCWBYa_gZGW-JGg3LefX8EEHF_ELAdh1IOKpFE88i2FZx-2RUScRYQ8IryIUT9A-WGiCWzLaXKkKjpEAo94W2ESL7uR9IIXljFmCRxbOdXN-a5_zSHbkxgc32MwfI8hbNQ9rBCcrEBwsgLBqmK9fIeH-uhkBaKTFYhGVkTdhMsqzw0lz0DkGYic5MDoGSJahuj-w1gLZ6Uwr_MUuSuKtUbK8ZEvTQc8CypRn86yYRuQ-R7cfbA88v8EZAHpyr4ecKh6P0D3PvZz8xlwacvXljwXpNeQjGPI00yZHTy98Sl6iFKTYp9Kb6rfbMBUgEJ0cH3jYWPydSNYi89FLL3mOjaltsoQbNX2a1jvizMue7adok1thnSbEp_K9h7QjgdCOx4I3_EgEpakRNtVM2wKoBstcy2bcqKFnGghJ1rIiJa5BPkxQX5MkBMTlLNTbirVyk3aLmtTVjTc1nE0ZI17sUGcwhxHRydYIzm4E7TRD9roR2Y04nmtsmroFN9i3BBinTu3bd85yuMVgfrZSOFP5A2OaMJsj1Z7dLqPPtVh6wA7OefUI07G3teMty_YSVJ2i_acYvqI_QxlJw3nVgyN2XcjG2f4NCcH08oMpk-Y7NHRHi326DxggNjef_sDjsS5VJA4tysy34hL1NtV4hQs8QuW-AVLjKp0Uu9aNi0gYdgr3Qxwkoh_IelvM8V0gyTTDZIfidRAdWqWOjXLe3GT9-Qm883dCetJO02pfp1T_9xW_3DWd82eZlEwraV2SVO7pKld0tQuafosaUv5daVRzU8P1IOvEmm-2Wo0jNszmijRwHv9qGrsGBtY2rBxmibQ_TT9A3vViWgxFQAA"
# todo: https://github.com/Cvolton/GMDprivateServer/blob/master/incl/levels/uploadGJLevel.php#L53
DEFAULT_EXTRA_STRING = "29_29_29_40_29_29_29_29_29_29_29_29_29_29_29_29"
# gddocs:
# > A random gzip compressed string
# i'm not sure it has any use; but setting it to an empty one .. works ?
DEFAULT_LEVEL_INFO = ""
# typically, you'd start right here
def decode(level_data : String)
io = IO::Memory.new(Base64.decode(level_data))
@ -20,9 +28,9 @@ module CrystalGauntlet::Level
end
end
def array_to_hash(arr : Array(String)) : Hash(String, String)
def array_to_hash(arr)
key = nil
hash = Hash(String, String).new
hash = Hash(typeof(arr[0]), typeof(arr[1])).new
arr.each() do |val|
if key == nil
key = val
@ -39,4 +47,8 @@ module CrystalGauntlet::Level
return objects
end
def gmd_parse(gmd_file : String)
Level.array_to_hash(XML.parse(gmd_file).first_element_child.not_nil!.children.reject { |node| node.type == XML::Node::Type::TEXT_NODE }.map { |node| node.children.to_s})
end
end

View File

@ -0,0 +1,43 @@
require "ecr"
require "xml"
include CrystalGauntlet
CrystalGauntlet.template_endpoints["/tools/reupload"] = ->(context : HTTP::Server::Context) {
context.response.content_type = "text/html"
error = nil
level_id = nil
body = context.request.body
if body
begin
params = URI::Params.parse(body.gets_to_end)
remote_level_id = params["level_id"]
resp = HTTP::Client.get "https://history.geometrydash.eu/api/v1/level/#{remote_level_id}/"
if resp.status_code != 200
raise "Recieved #{resp.status_code}"
end
data = JSON.parse(resp.body)
level = data["records"].as_a
.select { |rec| rec["level_string_available"] == true }
.sort { |a, b| a["real_date"].as_s <=> b["real_date"].as_s }
.first
gmd_file = HTTP::Client.get "https://history.geometrydash.eu/level/#{remote_level_id}/#{level["id"]}/download/"
level_data = Level.gmd_parse(gmd_file.body)
# todo: deduplicate this and level uploads
next_id = IDs.get_next_id("levels")
# todo: reupload as reupload acc
DATABASE.exec("insert into levels (id, name, user_id, description, original, game_version, binary_version, password, requested_stars, unlisted, version, extra_data, level_info, editor_time, editor_time_copies, song_id, length, objects, coins, has_ldm, two_player) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", next_id, Clean.clean_special(level_data["k2"]), 1, Base64.decode_string(Base64.decode_string(level_data["k3"])), level_data["k42"].to_i32, level_data["k17"].to_i32, (level_data["k50"]? || "0").to_i32, level_data["k41"].to_i32 == "0" ? nil : level_data["k41"].to_i32, level_data["k66"].to_i32, 0, level_data["k16"].to_i32, Clean.clean_special(level["extra_string"].as_s? || Level::DEFAULT_EXTRA_STRING), Level::DEFAULT_LEVEL_INFO, (level_data["k80"]? || "0").to_i32, (level_data["k81"]? || "0").to_i32, (level_data["k8"]? || "0") == "0" ? level_data["k45"] : level_data["k8"], level["length"].as_i, level_data["k48"], (level_data["k64"]? || "0").to_i, (level_data["k72"]? || "0").to_i, (level_data["k43"]? || "0").to_i)
File.write("data/#{next_id.to_s}.lvl", Base64.decode(level_data["k4"]))
rescue error
end
end
ECR.embed("./public/template/reupload.ecr", context.response)
}

View File

@ -3,6 +3,8 @@ require "ecr"
include CrystalGauntlet
CrystalGauntlet.template_endpoints["/tools/song_search"] = ->(context : HTTP::Server::Context) {
context.response.content_type = "text/html"
error = nil
songs = nil
result_limit = 10