Package: bfportal-grpc
Battlefield Portal web-grpcThis npm and python package can be used to directly call thehttps://portal.battlefield.com/api.
we're making this public since you can read the javascript of the website and figure this out yourself easily anyway, but we want to make sure only 1 github repo has to be kept in sync with the api and the rest that uses it just has to update a package and a few code changes to still have it work.https://www.npmjs.com/package/bfportal-grpchttps://pypi.org/project/bfportal-grpc/exampleimport{CommunityGamesClient,communitygames}from'bfportal-grpc'constcommunityGames=newCommunityGamesClient('https://kingston-prod-wgw-envoy.ops.dice.se',null)constmetadata={'x-dice-tenancy':'prod_default-prod_default-kingston-common','x-gateway-session-id':sessionId,'x-grpc-web':'1','x-user-agent':'grpc-web-javascript/0.1',}constrequest=newcommunitygames.GetPlaygroundRequest()request.setPlaygroundid(testPlayground)constresponse=awaitcommunityGames.getPlayground(request,metadata)constmodRules=response.getPlayground()?.getOriginalplayground()?.getModrules()?.getCompatiblerules()?.getRules()if(modRulesinstanceofUint8Array){console.log(newTextDecoder().decode(modRules))}constplaygroundName=response.getPlayground()?.getOriginalplayground()?.getName()the proto files are accessable directly via "node_modules/bfportal-grpc/proto/communitygames.proto" to for example decode to json:import{load}from'protobufjs'// use reponse from previous exampleconstroot=awaitload('node_modules/bfportal-grpc/proto/communitygames.proto')constAwesomeMessage=root.lookupType('web.communitygames.PlaygroundInfoResponse')constdecoded=AwesomeMessage.decode(response.serializeBinary())constjson_str=JSON.stringify(decoded,null,4)non-async exampleimport{CommunityGamesClient,communitygames}from'bfportal-grpc'constcommunityGames=newCommunityGamesClient('https://kingston-prod-wgw-envoy.ops.dice.se',null)constmetadata={'x-dice-tenancy':'prod_default-prod_default-kingston-common','x-gateway-session-id':sessionId,'x-grpc-web':'1','x-user-agent':'grpc-web-javascript/0.1',}constrequest=newcommunitygames.GetPlaygroundRequest()request.setPlaygroundid('bbe433c0-13fa-11ed-bc32-24a8c2c0764e')constcall=communityGames.getPlayground(request,metadata,(_err:grpcWeb.Error,response:communitygames.PlaygroundInfoResponse)=>{// console.log("err:", _err)varmodRules=response.getPlayground()?.getOriginalplayground()?.getModrules()?.getCompatiblerules()?.getRules()if(modRulesinstanceofUint8Array){console.log(newTextDecoder().decode(modRules))}load('node_modules/bfportal-grpc/proto/communitygames.proto',function(err,root){if(err)throwerrif(root==undefined)returnconstAwesomeMessage=root.lookupType('web.communitygames.PlaygroundInfoResponse')letdecoded=AwesomeMessage.decode(response.serializeBinary())fs.writeFile('test.json',JSON.stringify(decoded,null,4),function(err:any){if(err){console.log(err)}})})})pythonfor python you can use the 'sonora' package to do grpc-webimportasyncioimportsonora.aiofrombfportal_grpcimportcommunitygames_pb2,communitygames_pb2_grpc,access_token,authentication_pb2,authentication_pb2_grpcasyncdefmain():cookie=access_token.Cookie(sid="",remid="")token=awaitaccess_token.getBf2042GatewaySession(cookie)asyncwithsonora.aio.insecure_web_channel(f"https://kingston-prod-wgw-envoy.ops.dice.se")aschannel:stub=authentication_pb2_grpc.AuthenticationStub(channel)auth_response:authentication_pb2.AuthResponse=awaitstub.viaAuthCode(authentication_pb2.AuthRequest(platform=1,authCode=token,redirectUri='https://portal.battlefield.com/'),metadata=(('x-dice-tenancy','prod_default-prod_default-kingston-common'),('x-grpc-web','1'),('x-user-agent','grpc-web-javascript/0.1')))stub=communitygames_pb2_grpc.CommunityGamesStub(channel)response:communitygames_pb2.PlaygroundInfoResponse=awaitstub.getPlayground(communitygames_pb2.GetPlaygroundRequest(playgroundId="10992a10-461a-11ec-8de0-d9f491f92236"),metadata=(('x-dice-tenancy','prod_default-prod_default-kingston-common'),('x-gateway-session-id',auth_response.sessionId),('x-grpc-web','1'),('x-user-agent','grpc-web-javascript/0.1')))print(response.playground.originalPlayground.name)if__name__=="__main__":asyncio.run(main())current build method from proto to javascript via pythonneeds proto-compile, which can be installed with:pip3 install proto-compileand build with:proto-compile --clear-output-dirs --verbosity=1 ./proto ./src/proto grpc-web --grpc_web_out_options="import_style=typescript,mode=grpcweb"building for python requires grpcio-tools, which can be installed with:pip3 install grpcio-toolsand build with:python3 -m grpc_tools.protoc -I. --python_out=./bfportal_grpc --grpc_python_out=./bfportal_grpc ./proto/communitygames.proto ./proto/localization.proto ./proto/authentication.proto ./proto/reporting.protopython package used:https://github.com/romnn/proto-compilePushing your changespackage versions can be made withnpm run buildandnpm version patchgit push --tags origin mainto release.
for python patch withnpm run build:python,npm run python:setimportsandpoetry build.example library used:https://github.com/tomchen/example-typescript-package