2022-12-30 17:04:27 +01:00
require " uri "
require " base64 "
include CrystalGauntlet
2022-12-31 05:03:36 +01:00
# things might break if you modify this
levels_per_page = 10
2022-12-30 17:04:27 +01:00
CrystalGauntlet . endpoints [ " /getGJLevels21.php " ] = - > ( body : String ) : String {
params = URI :: Params . parse ( body )
puts params . inspect
2022-12-31 05:03:36 +01:00
# where [...]
queryParams = [ " unlisted = 0 " ] # don't leave the default empty!!
# order by [...]
order = " levels.created_at desc "
2022-12-31 20:05:39 +01:00
page_offset = ( params [ " page " ]? || " 0 " ) . to_i * levels_per_page
2022-12-31 05:03:36 +01:00
searchQuery = params [ " str " ]? || " "
# filters
if params [ " featured " ]? == " 1 "
queryParams << " featured = 1 "
end
if params [ " original " ]? == " 1 "
queryParams << " original is null "
end
if params [ " coins " ]? == " 1 "
queryParams << " rated_coins = 1 and levels.coins != 0 "
end
if params [ " epic " ]? == " 1 "
queryParams << " epic = 1 "
end
if params [ " uncompleted " ]? == " 1 "
# todo
# $completedLevels = ExploitPatch::numbercolon($_POST["completedLevels"]);
# $params[] = "NOT levelID IN ($completedLevels)";
end
if params [ " onlyCompleted " ]? == " 1 "
# todo
# $completedLevels = ExploitPatch::numbercolon($_POST["completedLevels"]);
# $params[] = "levelID IN ($completedLevels)";
end
if params [ " song " ]?
if params [ " customSong " ]? && params [ " customSong " ]? != " "
# todo
else
2022-12-31 20:05:39 +01:00
queryParams << " song_id = ' #{ params [ " song " ] . to_i } ' "
2022-12-31 05:03:36 +01:00
end
end
if params [ " twoPlayer " ]? == " 1 "
queryParams << " two_player = 1 "
end
if params [ " star " ]? == " 1 "
queryParams << " levels.stars is not null "
end
if params [ " noStar " ]? == " 1 "
queryParams << " levels.stars is null "
end
if params [ " gauntlet " ]?
# todo
end
if params [ " len " ]?
# todo
end
if params [ " diff " ]? && params [ " diff " ]? != " - "
case params [ " diff " ]?
when " -1 "
2022-12-31 07:59:44 +01:00
queryParams << " difficulty is null and community_difficulty is null " # NA
2022-12-31 05:03:36 +01:00
when " -2 "
puts " demon :) "
case params [ " demonFilter " ]?
when " 1 "
queryParams << " demon_difficulty = #{ DemonDifficulty :: Easy . value } "
when " 2 "
queryParams << " demon_difficulty = #{ DemonDifficulty :: Medium . value } "
when " 3 "
queryParams << " demon_difficulty = #{ DemonDifficulty :: Hard . value } "
when " 4 "
queryParams << " demon_difficulty = #{ DemonDifficulty :: Insane . value } "
when " 5 "
queryParams << " demon_difficulty = #{ DemonDifficulty :: Extreme . value } "
end
2022-12-31 07:59:44 +01:00
queryParams << " difficulty = #{ LevelDifficulty :: Demon . value } or (difficulty is null and community_difficulty = #{ LevelDifficulty :: Demon . value } ) "
2022-12-31 05:03:36 +01:00
when " -3 "
2022-12-31 07:59:44 +01:00
queryParams << " difficulty = #{ LevelDifficulty :: Auto . value } or (difficulty is null and community_difficulty = #{ LevelDifficulty :: Auto . value } ) "
2022-12-31 05:03:36 +01:00
else
# easy, normal, hard, harder, insane
# todo
end
end
# level search type
case params [ " type " ]
when " 0 " , " 15 " , nil # default sort (gdw is 15)
order = " likes desc "
when " 1 " # most downloaded
order = " downloads desc "
when " 2 " # most liked
order = " likes desc "
when " 3 " # trending
# todo
when " 5 " # made by user
2022-12-31 20:05:39 +01:00
queryParams << " levels.user_id = #{ searchQuery . to_i } " # (you can't sql inject with numbers)
2022-12-31 05:03:36 +01:00
when " 6 " , " 17 " # featured (gdw is 17)
# todo: order by feature date
queryParams << " featured = 1 "
when " 16 " # hall of fame (epic)
# todo: order by epic date
queryParams << " epic = 1 "
when " 7 " # magic
# todo
when " 10 " , " 19 " # map packs
2022-12-31 18:48:15 +01:00
order = " map_pack_links.idx asc "
2022-12-31 20:05:39 +01:00
queryParams << " levels.id in ( #{ searchQuery . split ( " , " ) . map { | v | v . to_i } . join ( " , " ) } ) "
2022-12-31 05:03:36 +01:00
when " 11 " # rated
# todo: order by rate date
queryParams << " levels.stars is not null "
when " 12 " # followed
# todo
when " 13 " # friends
# todo
when " 21 " # daily
# todo
when " 22 " # weekly
# todo
when " 23 " # event (unused)
# todo
end
# todo: search query
where_str = " where ( #{ queryParams . join ( " ) and ( " ) } ) "
2023-01-02 07:51:41 +01:00
# todo: switch join users to left join to avoid losing levels to the shadow realm after a user vanishes
query_base = " from levels join users on levels.user_id = users.id left join map_pack_links on map_pack_links.level_id = levels.id #{ where_str } order by #{ order } "
2022-12-31 05:03:36 +01:00
puts query_base
level_count = DATABASE . scalar ( " select count(*) #{ query_base } " ) . as ( Int64 )
2022-12-30 17:04:27 +01:00
results = [ ] of String
users = [ ] of String
songs = [ ] of String
hash_data = [ ] of Tuple ( Int32 , Int32 , Bool )
2023-01-02 07:51:41 +01:00
# fucking help
DATABASE . query_all ( " select levels.id, levels.name, levels.user_id, levels.description, levels.original, levels.game_version, levels.requested_stars, levels.version, levels.song_id, levels.length, levels.objects, levels.coins, levels.has_ldm, levels.two_player, levels.downloads, levels.likes, levels.difficulty, levels.community_difficulty, levels.demon_difficulty, levels.stars, levels.featured, levels.epic, levels.rated_coins, users.username, users.udid, users.account_id, users.registered #{ query_base } limit #{ levels_per_page } offset #{ page_offset } " , as : { Int32 , String , Int32 , String , Int32 | Nil , Int32 , Int32 | Nil , Int32 , Int32 , Int32 , Int32 , Int32 , Bool , Bool , Int32 , Int32 , Int32 | Nil , Int32 | Nil , Int32 | Nil , Int32 | Nil , Bool , Bool , Bool , String , String | Nil , Int32 | Nil , Bool } ) . map ( ) do | id , name , user_id , description , original , game_version , requested_stars , version , song_id , length , objects , coins , has_ldm , two_player , downloads , likes , set_difficulty_int , community_difficulty_int , demon_difficulty_int , stars , featured , epic , rated_coins , user_username , user_udid , user_account_id , user_registered |
set_difficulty = set_difficulty_int && LevelDifficulty . new ( set_difficulty_int )
community_difficulty = community_difficulty_int && LevelDifficulty . new ( community_difficulty_int )
difficulty = set_difficulty || community_difficulty
demon_difficulty = demon_difficulty_int && DemonDifficulty . new ( demon_difficulty_int )
# https://github.com/Cvolton/GMDprivateServer/blob/master/incl/levels/getGJLevels.php#L266
results << Format . fmt_hash ( {
1 = > id ,
2 = > name ,
5 = > version ,
6 = > user_id ,
8 = > 10 ,
9 = > difficulty ? difficulty . to_star_difficulty : 0 , # 0=N/A 10=EASY 20=NORMAL 30=HARD 40=HARDER 50=INSANE 50=AUTO 50=DEMON
10 = > downloads ,
12 = > ! Songs . is_custom_song ( song_id ) ? song_id : 0 ,
13 = > game_version ,
14 = > likes ,
17 = > difficulty && difficulty . demon? ,
# 0 for n/a, 10 for easy, 20, for medium, ...
43 = > ( demon_difficulty || DemonDifficulty :: Hard ) . to_demon_difficulty ,
25 = > difficulty && difficulty . auto? ,
18 = > stars || 0 ,
19 = > featured ,
42 = > epic ,
45 = > objects ,
3 = > GDBase64 . encode ( description ) ,
15 = > length ,
30 = > original || 0 ,
31 = > two_player ,
37 = > coins ,
38 = > rated_coins ,
39 = > requested_stars || 0 ,
46 = > 1 ,
47 = > 2 ,
40 = > has_ldm ,
35 = > Songs . is_custom_song ( song_id ) ? song_id : 0 ,
} )
users << " #{ user_id } : #{ user_username } : #{ user_registered ? user_account_id : user_udid } "
if Songs . is_custom_song ( song_id )
begin
song = Songs . fetch_song ( song_id , false )
rescue
else
if song != nil
song_name , song_author_id , song_author_name , song_size , song_download = song . not_nil!
songs << Format . fmt_song ( {
1 = > song_id ,
2 = > song_name ,
3 = > song_author_id ,
4 = > song_author_name ,
5 = > ( song_size || 0 ) / ( 1000 * 1000 ) ,
6 = > " " ,
10 = > song_download || " " ,
7 = > " " ,
8 = > " 1 "
} )
end
2022-12-31 14:25:43 +01:00
end
2022-12-30 17:04:27 +01:00
end
2023-01-02 07:51:41 +01:00
hash_data << { id , stars || 0 , rated_coins }
2022-12-30 17:04:27 +01:00
end
2022-12-31 05:03:36 +01:00
# `${amount}:${offset}:${levelsPerPage}`
searchMeta = " #{ level_count } : #{ page_offset } : #{ levels_per_page } "
2022-12-30 17:04:27 +01:00
2022-12-31 14:25:43 +01:00
res = [ results . join ( " | " ) , users . join ( " | " ) , songs . join ( " ~:~ " ) , searchMeta , CrystalGauntlet :: Hashes . gen_multi ( hash_data ) ] . join ( " # " )
2022-12-30 17:04:27 +01:00
puts res
res
}