rman

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 28, 2024 License: MIT Imports: 10 Imported by: 0

README

Riot Games RMAN Manifest Parser

Manifest Parser for downloading, updating games or viewing the files

Explanation

https://technology.riotgames.com/news/supercharging-data-delivery-new-league-patcher

Installation

go get -u github.com/meszmate/rman

Usage

This is only an example, but you can build a better downloader if you want. Check "Explanation" if you want to know how to update the game.

package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"time"

	"github.com/meszmate/rman"
)

const DownloadPath string = "/Users/meszmate/manifestparse/" // Leave it empty if you want to install to the current directory
const BaseURL string = "https://valorant.dyn.riotcdn.net/channels/public/bundles"
const max_retries int = 7

func main(){
	stime := time.Now().Unix()
    	b := rman.LoadFileBytes("/Users/meszmate/Downloads/EB9EF8EA7C032A8B.manifest")
    	manifest, err := rman.ParseManifestData(b)
    	if err != nil{
        	log.Fatalf(err.Error())
    	}
    	for _, f := range manifest.Files{
        	fpath := DownloadPath + f.Name
        	err := os.MkdirAll(filepath.Dir(fpath), os.ModePerm)
        	if err != nil {
            		log.Fatalf("Failed to create directories: %v", err)
        	}
        	file, err := os.Create(fpath)
        	if err != nil {
            		log.Fatalf("Failed to create file: %v", err)
        	}
        	defer file.Close()

        	for _, i := range f.Chunks{
            		chbytes := getChunkByURL(i.BundleID, i.BundleOffset, i.CompressedSize, max_retries)
            		if chbytes == nil{
                		fmt.Printf("%s Failed to get chunk %d, next...\n", fmt.Sprintf("%016X", i.BundleID), i.ChunkID)
				continue
			}
			file.Write(rman.Decompress(chbytes))
		}
		fmt.Println(fpath + " is successfully installed")
	}
	etime := time.Now().Unix()
	fmt.Printf("Successfully installed in %d seconds\n", etime-stime)
}

func getChunkByURL(BundleID uint64, offset uint32, size uint32, retries int) []byte{
	req, err := http.NewRequest("GET", fmt.Sprintf("%s/%016X.bundle", BaseURL, BundleID), nil)
	if err != nil{
		return nil
	}
	req.Header.Add("Range", fmt.Sprintf("bytes=%d-%d", offset, offset+size-1))
	retry := 0
	for retry < retries+1{
		newbytes := rman.LoadHttpReqestBytes(req)
		if newbytes != nil{
			return newbytes
		}
		retry++
	}
	return nil
}

Example 2

If you want faster download, i created a faster version

package main

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"time"

	"github.com/meszmate/rman"
)

const DownloadPath string = "/Users/meszmate/manifestparse/" // Leave it empty if you want to install to the current directory
const BaseURL string = "https://valorant.dyn.riotcdn.net/channels/public/bundles"
const max_retries int = 7

type Buff struct{
    BundleID uint64
    Data []byte
}

func main(){
	stime := time.Now().Unix()
	var buff *Buff = nil
	b := rman.LoadFileBytes("/Users/meszmate/Downloads/EB9EF8EA7C032A8B.manifest")
	manifest, err := rman.ParseManifestData(b)
	if err != nil{
	        log.Fatalf(err.Error())
	}
	for _, f := range manifest.Files{
	        fpath := DownloadPath + f.Name
	        err := os.MkdirAll(filepath.Dir(fpath), os.ModePerm)
	        if err != nil {
	            	log.Fatalf("Failed to create directories: %v", err)
	        }
	        file, err := os.Create(fpath)
	        if err != nil {
	            	log.Fatalf("Failed to create file: %v", err)
	        }
	        defer file.Close()
	
	        for _, i := range f.Chunks{
	            	if buff == nil || buff.BundleID != i.BundleID{
	                	bundleBytes := getBundleDataByURL(i.BundleID, max_retries)
	                	if bundleBytes == nil{
	                    		fmt.Printf("%s Failed to get chunk bundle %d, next...\n", fmt.Sprintf("%016X", i.BundleID), i.ChunkID)
	                    		continue
				}
	                	buff = &Buff{
	                    		BundleID: i.BundleID,
	                    		Data: bundleBytes,
				}
	            	}
	            	chbytes := buff.Data[i.BundleOffset:i.BundleOffset+i.CompressedSize]
	            	file.Write(rman.Decompress(chbytes))
	        }
	        fmt.Println(f.Name + " is successfully installed")
	}
	etime := time.Now().Unix()
	fmt.Printf("Successfully installed in %d seconds\n", etime-stime)
}
func getBundleDataByURL(BundleID uint64, retries int) []byte{
    	retry := 0
	for retry < retries+1{
		newbytes := rman.LoadURLBytes(fmt.Sprintf("%s/%016X.bundle", BaseURL, BundleID))
		if newbytes != nil{
			return newbytes
		}
		retry++
	}
	return nil
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Decompress

func Decompress(data []byte) []byte

func LoadFileBytes

func LoadFileBytes(url string) []byte

func LoadHttpReqestBytes

func LoadHttpReqestBytes(req *http.Request) []byte

func LoadURLBytes

func LoadURLBytes(url string) []byte

func ParseBody

func ParseBody(manifest *Manifest, data []byte) error

Types

type Chunk

type Chunk struct {
	CompressedSize   uint32
	UncompressedSize uint32
	ChunkID          uint64
	BundleOffset     uint32
	BundleID         uint64
}

type Directory

type Directory struct {
	DirectoryID uint64
	Name        string
}

type FileEntry

type FileEntry struct {
	ID       uint64
	FileSize uint32
	Name     string
	SymLink  string
	Flags    []Flag
	Chunks   []Chunk
}

type FirstDirectory

type FirstDirectory struct {
	DirectoryID uint64
	ParentID    uint64
	Name        string
}

type Flag

type Flag struct {
	FlagID uint8
	Name   string
}

type Manifest

type Manifest struct {
	ID    uint64
	Flags []Flag
	Files []FileEntry
}

func ParseManifestData

func ParseManifestData(data []byte) (*Manifest, error)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL