Example #1
0
// HomeHandler is the home of our website
func HomeHandler(w http.ResponseWriter, r *http.Request) {

	// Try to refresh player count
	refreshPlayerCount()

	// Get leaderboards
	leaderboards, err := steam.GetLeaderboards()
	if err != nil {
		common.Err("SERVER", fmt.Sprintf("%v", err))
	}

	// Prepare view
	var data IndexData

	// -- Paginate
	page := getPage(r)

	u, d, pagination := paginate.Paginate(len(leaderboards.List), page, LEADERBOARDSHOMECOUNT)

	data.Leaderboards = leaderboards.List[u:d]
	data.Page = pagination
	data.PlayerCount = playerCount

	// -- HTML rendering
	t, err := template.ParseFiles(layoutPath("default"), templatePath("index"))
	if err != nil {
		common.Err("SERVER", fmt.Sprintf("%v", err))
	} else {
		t.Execute(w, data)
	}
}
Example #2
0
// PlayerHandler gives details for a given player
func PlayerHandler(w http.ResponseWriter, r *http.Request) {

	// Get player object
	vars := mux.Vars(r)
	steamID, _ := vars["id"] // id should be safe thanks to routing

	players := steam.GetPlayersFromWeb(getAPIKey(), true, []string{steamID})

	if len(players) < 0 {
		http.Redirect(w, r, "/", http.StatusNotFound)
		return
	}

	player, ok := players[steamID]

	if ok == false {
		http.Redirect(w, r, "/", http.StatusNotFound)
		return
	}

	// Get data for player
	var p PlayerData
	p.Player = player
	p.Ranks = steam.GetPlayerEntries(steamID)

	// HTML rendering
	t, err := template.ParseFiles(layoutPath("default"), templatePath("player"))
	if err != nil {
		common.Err("SERVER", fmt.Sprintf("%v", err))
	} else {
		t.Execute(w, p)
	}
}
Example #3
0
// LeaderboardHandler displays information for a given leaderboard
func LeaderboardHandler(w http.ResponseWriter, r *http.Request) {

	// Get leaderboard object
	vars := mux.Vars(r)
	ldbID, _ := strconv.Atoi(vars["id"])

	l, err := steam.GetLeaderboard(ldbID)

	if err != nil {
		http.Redirect(w, r, "/", http.StatusNotFound)
		return
	}

	// Pagination
	page := getPage(r)
	u, d, pagination := paginate.Paginate(len(l.Entries), page, 100)

	data := LeaderboardData{
		Entries: l.Entries[u:d],
		Page:    pagination,
		Name:    l.Name,
		Count:   len(l.Entries),
		ID:      l.UID,
		Daily:   l.IsDaily(),
		LastUpdateDisplayable: l.LastUpdate.Format(time.Stamp),
	}

	// HTML rendering
	t, err := template.ParseFiles(layoutPath("default"), templatePath("leaderboard"))
	if err != nil {
		common.Err("SERVER", fmt.Sprintf("%v", err))
	} else {
		t.Execute(w, data)
	}
}
// GetLeaderboard returns a leaderboard object with the given Steam id
func GetLeaderboard(steamID int) (common.Leaderboard, error) {

	l, err := common.GetLeaderboardFromDB(steamID)

	// Now load entries
	// -- Update first
	ttl := time.Duration(24) * time.Hour
	if l.IsDaily() {
		ttl = time.Duration(30) * time.Minute
	}

	if l.LastUpdate.Add(ttl).Before(time.Now()) {
		loadLeaderboardFromWeb(l)
	}

	// -- Read from DB
	entries, err := common.GetEntriesFromDB(l.UID)

	if err != nil {
		return l, err
	}

	// ---------

	// Additionnal datas
	for i := 0; i < len(entries); i++ {
		entry := &entries[i]

		// Metadata
		t, err := hex.DecodeString(entry.MetadataRaw)

		if err == nil {
			if len(t) > 0 {

				// Metadata are 32 bits integer = 4 * 8 bits bytes
				metadatas := []int{}
				for m := 0; m < len(t); m += 4 {

					var val int32
					buf := bytes.NewBuffer(t[m : m+4])
					binary.Read(buf, binary.LittleEndian, &val)

					metadatas = append(metadatas, int(val))
				}

				specificFunctions.UseMetadata(entry, metadatas)
			}
		} else {
			common.Err("DATABASE", fmt.Sprintf("Error parsing metadata: %v", err))
		}
	}

	l.Entries = entries

	return l, nil
}
// GetPlayerEntries returns all entries for this player
func GetPlayerEntries(playerID string) []common.PlayerRank {

	ranks, err := common.GetPlayerEntriesDB(playerID)

	if err != nil {
		common.Err("DATABASE", fmt.Sprintf("GetPlayerEntriesDB: %v", err))
	}

	return ranks
}
func loadLeaderboardsFromWeb() error {

	common.Info("LEADERBOARDS", "Reloading all leaderboards from web...")

	var ldbs common.LeaderboardsList

	// Parse new from URL
	url := fmt.Sprintf("http://steamcommunity.com/stats/%v/leaderboards/?xml=1", appID)

	// Get all leaderboards for the game
	if err := MakeAPICall(url, true, &ldbs); err != nil {
		common.Err("LEADERBOARDS", fmt.Sprintf("%s", err))
		return err
	}

	// Exclude some leaderboards we don't want to show
	for i := 0; i < len(excludedLeaderboardIDs); i++ {
		for j := 0; j < len(ldbs.List); j++ {
			if ldbs.List[j].SteamID == excludedLeaderboardIDs[i] {
				// Remove the element
				ldbs.List = append(ldbs.List[:j], ldbs.List[j+1:]...)
			}
		}
	}

	// Parse dates
	for i := 0; i < len(ldbs.List); i++ {
		l := &ldbs.List[i]

		l.LastUpdate = time.Date(1988, time.April, 29, 3, 0, 0, 0, time.UTC)
		l.Date = specificFunctions.GetDate(l)
	}

	// Save to database
	for _, l := range ldbs.List {

		// Exists?
		existingLeaderboard, _ := common.GetLeaderboardFromDB(l.SteamID)

		if existingLeaderboard.Name == "" {
			common.InsertLeaderboardDB(l)
		} else {
			common.UpdateLeaderboardDB(l)
		}
	}

	lastLeaderboardRefresh = time.Now()

	return nil
}
// loadLeaderboardFromWeb fetch data from Steam
func loadLeaderboardFromWeb(l common.Leaderboard) {

	common.Info("LEADERBOARDS", fmt.Sprintf("Loading leaderboard %v from web...", l.SteamID))

	resp, err := http.Get(l.URL)
	if err != nil {
		common.Err("LEADERBOARDS", fmt.Sprintf("%s", err))
		return
	}

	defer resp.Body.Close()
	leaderboardBuffer, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		common.Err("LEADERBOARDS", fmt.Sprintf("%s", err))
		return
	}

	// Parse XML to get objects

	// LeaderboardEntriesRequest is the list of score entries.
	// It is only used for the marshaller
	requestType := struct {
		EntriesContainer struct {
			Entries []common.LeaderboardEntry `xml:"entry"`
		} `xml:"entries"`
	}{}

	xml.Unmarshal(leaderboardBuffer, &requestType)

	entries := requestType.EntriesContainer.Entries

	// Save to database
	// -- CLean all previous
	common.DeleteEntriesDB(l)

	// -- Save & get players
	var players map[string]common.Player
	players = make(map[string]common.Player)

	if len(entries) > 0 {
		var steamIDsToLoad []string
		for _, e := range entries {

			p, _ := common.GetPlayerWithSteamIDFromDB(e.SteamID)

			updatePlayer := true

			if p.UID != 0 {
				// Check last update
				if p.LastUpdate.Add(time.Duration(1) * time.Hour).After(time.Now()) {
					players[e.SteamID] = p
					updatePlayer = false
				}
			}

			if updatePlayer {
				steamIDsToLoad = append(steamIDsToLoad, e.SteamID)
			}
		}

		// Update = web to DB
		for steamID, p := range GetPlayersFromWeb(apiKey, false, steamIDsToLoad) {

			// Save player
			common.InsertOrUpdatePlayerDB(&p)

			players[steamID] = p
		}
	}

	// -- Insert all new ones
	for _, e := range requestType.EntriesContainer.Entries {

		// Set player
		e.Player = players[e.SteamID]
		e.PlayerUID = e.Player.UID

		// Save entry
		common.InsertEntryDB(l, e)
	}

	l.LastUpdate = time.Now()

	common.UpdateLeaderboardDB(l)

	common.Info("LEADERBOARDS", fmt.Sprintf("Loading leaderboard %v completed!", l.SteamID))
}
Example #8
0
// Start the server.
func Start() {

	common.Info("SERVER", "Loading...")

	steam.DebugRequests = false

	// Check API key
	// Request API Key: http://steamcommunity.com/dev/apikey
	err := godotenv.Load()
	if err != nil {
		common.Err("SERVER", fmt.Sprintf("Error loading .env file: %v ", err))
	} else {
		steamAPIkey := getAPIKey()

		if steamAPIkey == "" {
			common.Warn("SERVER", "Missing Steam API key, some features will not work. Get one at http://steamcommunity.com/dev/apikey and add it to a .env file for key STEAM_API_KEY.")
		} else {
			common.Info("SERVER", "Steam key found!")
		}
	}

	// Configure
	common.ConfigureDB(config.DbFile)
	steam.Configure(getAPIKey(), STEREDENN, []int{1006063}, steredenn.Steredenn{})

	// Get player count
	refreshPlayerCount()

	common.Info("SERVER", "Loading completed!")

	// Initial loading?
	if config.LoadAllOnStart {

		common.Info("SERVER", "Starting complete data reload...")

		leaderboards, _ := steam.GetLeaderboards()

		for _, l := range leaderboards.List {
			steam.GetLeaderboard(l.SteamID)
		}

		common.Info("SERVER", "Data reload completed!")
	}

	// Routing
	r := mux.NewRouter()
	r.HandleFunc("/", HomeHandler)
	r.HandleFunc("/{page:[0-9]+}", HomeHandler)
	r.HandleFunc("/leaderboard/{id:[0-9]+}", LeaderboardHandler)
	r.HandleFunc("/leaderboard/{id:[0-9]+}/{page:[0-9]+}", LeaderboardHandler)
	r.HandleFunc("/player/{id:[0-9]+}", PlayerHandler)

	// Use a custom file server in dev mode to serve static file.
	// Useless in production (nginx will handle that).
	if config.Dev {
		r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(config.StaticFolder))))
	}

	http.Handle("/", r)
	http.ListenAndServe(":3000", nil)
}