program downloader; uses fphttpclient, base64, opensslsockets, fpjson, jsonparser, SysUtils, process, Classes; const authString = '***REMOVED***'; var gameId: Integer; gameData: TJSONData; client: TFPHTTPClient; tarFile: String; function getGameData(var client: TFPHTTPClient; gameId: Integer; out gameData: TJSONData): Boolean; const url = 'https://rpi.narnian.us/games/get_game/'; var jData: TJSONData; begin writeln('start get game data'); client.AllowRedirect := true; try jData := GetJSON(client.Get(url+IntToStr(gameId))); gameData := jData; getGameData := true; Except getGameData := false; end; end; function downloadGameTar(var client: TFPHTTPClient; gameId: Integer): String; const url = 'https://rpi.narnian.us/games/download/windows/'; var tarFile: TFileStream; tarFileName: String; begin writeln('start download tar'); client.AllowRedirect := true; tarFileName := gameData.FindPath('title_sanitized').AsString+'.tar'; tarFile := TFileStream.Create(tarFileName, fmCreate); client.Get(url+IntToStr(gameId), tarFile); tarFile.Free; downloadGameTar := tarFileName; end; procedure extractTar(fileName: String); var s: AnsiString; begin writeln('start extract tar'); RunCommand('tar.exe', ['-xf', fileName], s); end; procedure copyFile(oldFile, newFile: AnsiString); var splitDir: TStringArray; s: String; newDir: String = ''; source, dest: TFileStream; begin splitDir := newFile.Split(['\', '/']); for s in splitDir do begin if not (s = splitDir[Length(splitDir)-1]) then begin newDir := newDir + s + '/'; CreateDir(newDir); end; end; source := TFileStream.Create(oldFile, fmOpenRead); dest := TFileStream.Create(newFile, fmCreate); dest.CopyFrom(source, source.Size); source.Free; dest.Free; end; procedure moveFile(oldFile, newFile: AnsiString); begin copyFile(oldFile, newFile); DeleteFile(oldFile); end; procedure proccessHashFiles; var files: TJSONData; hash: String; hashPaths: TJSONArray; i, j: Integer; begin writeln('start proccess hash files'); files := gameData.FindPath('windows.files'); for i := 0 to files.count-1 do begin hash := TJSONObject(files).Names[i]; hashPaths := TJSONArray(files.FindPath(hash)); for j := 0 to hashPaths.Count-1 do begin if j = hashPaths.Count-1 then moveFile(hash, hashPaths.Strings[j]) else copyFile(hash, hashPaths.Strings[j]); end; end; end; begin if ParamCount > 0 then begin gameId := StrToInt(ParamStr(1)); client := TFPHTTPClient.Create(nil); client.AddHeader('Authorization', 'Basic '+base64.EncodeStringBase64(authString)); if getGameData(client, gameId, gameData) then begin tarFile := downloadGameTar(client, gameId); extractTar(tarFile); proccessHashFiles; end else begin WriteLn('Invalid game id given'); end; end else begin WriteLn('No game id was given'); end; end.