Skip to content

Commit

Permalink
Update card generation
Browse files Browse the repository at this point in the history
  • Loading branch information
Nicconike committed May 29, 2024
1 parent 39f590d commit 1a91a3c
Show file tree
Hide file tree
Showing 12 changed files with 322 additions and 86 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/quality-check.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
name: Quality Check

on:
push:
branches:
- master
schedule:
# Runs every Monday at 12AM IST (UTC+5:30)
- cron: "30 18 * * 0"
workflow_dispatch:
pull_request:
branches:
- master
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/steam-stats.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ on:
# Runs every Monday at 12AM IST (UTC+5:30)
- cron: "30 18 * * 0"
workflow_dispatch:
pull_request:
branches:
- master

jobs:
update-readme:
Expand Down
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
[![Visitor Badge](https://badges.pufler.dev/visits/nicconike/steam-stats)](https://badges.pufler.dev)

<!-- Steam-Stats start -->
![Steam Games Stats](https://github.com/Nicconike/Steam-Stats/blob/master/assets/recently_played_games.svg?sanitize=true)
<!-- Steam-Stats end -->

<!-- Steam-Workshop start -->
![Steam Workshop Stats](https://github.com/Nicconike/Steam-Stats/blob/master/assets/steam_workshop_stats.svg?sanitize=true)
<!-- Steam-Workshop end -->
121 changes: 96 additions & 25 deletions api/card.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""Generate Card for Steam Stats"""
import json
"""Generate Cards for Steam Stats"""
import datetime
import os
from dotenv import load_dotenv
from steam_stats import get_player_summaries
from steam_stats import get_player_summaries, get_recently_played_games

load_dotenv()

Expand All @@ -11,25 +11,38 @@
STEAM_ID = os.getenv("STEAM_ID")


def format_unix_time(unix_time):
"""Convert Unix time to human-readable format"""
return datetime.datetime.fromtimestamp(unix_time).strftime("%d/%m/%Y")


def generate_card_for_player_summary(player_data):
"""Generate HTML content based on Steam Player Summary Data"""
if not player_data:
return None
summary_data = player_data["response"]["players"][0]
personaname = summary_data["personaname"]
personastate = summary_data["personastate"]
avatarfull = summary_data["avatarfull"]
loccountrycode = summary_data["loccountrycode"]
lastlogoff = summary_data["lastlogoff"]
timecreated = summary_data["timecreated"]
gameextrainfo = summary_data.get("gameextrainfo", None)

# Convert lastlogoff & timecreated from Unix time to human-readable format
lastlogoff_str = format_unix_time(lastlogoff)
timecreated_str = format_unix_time(timecreated)

personastate_map = {
0: 'Offline',
1: 'Online',
2: 'Busy',
3: 'Away',
4: 'Snooze',
5: 'Looking to trade',
6: 'Looking to play'
0: "Offline",
1: "Online",
2: "Busy",
3: "Away",
4: "Snooze",
5: "Looking to trade",
6: "Looking to play"
}
personastate_value = personastate_map.get(personastate, 'Unknown')
personastate_value = personastate_map.get(personastate, "Unknown")

html_content = f"""
<!DOCTYPE html>
Expand All @@ -41,7 +54,7 @@ def generate_card_for_player_summary(player_data):
<style>
.card {{
width: 100%;
max-width: 600px;
max-width: 500px;
margin: auto;
border: 2px solid #000;
padding: 20px;
Expand Down Expand Up @@ -75,27 +88,85 @@ def generate_card_for_player_summary(player_data):
<img id="flag" class="flag"
src="https://flagcdn.com/w320/{loccountrycode.lower()}.png" alt="Flag">
</p>
<p id="lastlogoff">Last Logoff: {lastlogoff_str}</p>
<p id="lastlogoff">Gaming Since: {timecreated_str}</p>
{"<p id='game'>Currently Playing: <span id='game-info'>" +
gameextrainfo + "</span></p>" if gameextrainfo else ""}</div>
gameextrainfo + "</span></p>" if gameextrainfo else ""}
</div>
</div>
</body>
</html>
"""
with open("../assets/steam_summary.html", "w", encoding="utf-8") as file:
file.write(html_content)

return (
"![Steam Summary]("
"https://github.com/Nicconike/Steam-Stats/blob/master/assets/steam_summary.html"
"?sanitize=true)"
)


def generate_card_for_played_games(games_data):
"""Generate HTML content for recently played games with a horizontal bar graph"""
if not games_data:
return None

max_playtime = games_data["response"]["games"][0]["playtime_2weeks"]

# Generate the progress bars with repeating styles
progress_bars = ""
for i, game in enumerate(games_data["response"]["games"]):
if "name" in game and "playtime_2weeks" in game:
name = game["name"]
playtime = game["playtime_2weeks"]
img_icon_url = f"https://media.steampowered.com/steamcommunity/public/images/apps/{
game["appid"]}/{game["img_icon_url"]}.jpg"
normalized_playtime = (playtime / max_playtime) * 100
display_time = f"{playtime} mins" if playtime < 60 else f"{
playtime / 60:.2f} hrs"
progress_bars += f"""
<div class="bar-container">
<img src="{img_icon_url}" alt="{name}" class="game-icon">
<progress id="p{i}" value="{normalized_playtime}" max="100"
class="bar-{(i % 6) + 1}"></progress>
<span class="game-info"><b>{name} ({display_time})</b></span>
</div>
"""

html_content = f"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Recently Played Games in Last 2 Weeks</title>
<link rel="stylesheet" href="../assets/style.css">
</head>
<body>
<div class="card">
<div class="content">
<h2>Recently Played Games</h2>
{progress_bars}
</div>
</div>
</body>
</html>
"""
return html_content

with open("../assets/recently_played_games.html", "w", encoding="utf-8") as file:
file.write(html_content)

def save_to_file(data, filename):
"""Save fetched data to a file in JSON format"""
if data is not None:
with open(filename, 'w', encoding='utf-8') as file:
# Use json.dump to write the JSON data to the file
json.dump(data, file, indent=4)
print(f"Data saved to {filename}")
else:
print("No data to save")
return (
"![Steam Games Stats]("
"https://github.com/Nicconike/Steam-Stats/blob/master/assets/recently_played_games.html"
"?sanitize=true)"
)


if __name__ == "__main__":
summary = get_player_summaries()
html = generate_card_for_player_summary(summary)
print(html)
recent_game = get_recently_played_games()
summary_content = generate_card_for_player_summary(summary)
recently_played_games = generate_card_for_played_games(
recent_game)
70 changes: 24 additions & 46 deletions api/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,17 @@
import numpy as np
import pandas as pd
import plotly.graph_objects as go
from steam_stats import get_recently_played_games
from steam_stats import get_player_summaries, get_recently_played_games
from steam_workshop import fetch_workshop_item_links, fetch_all_workshop_stats
import pygal
from card import generate_card_for_player_summary, generate_card_for_played_games

# Secrets Configuration
STEAM_ID = os.getenv("STEAM_CUSTOM_ID")


def generate_svg_for_recently_played_games(player_data):
"""Generate SVG for Recently Played Games in Steam in the last 2 weeks"""
bar_chart = pygal.HorizontalBar(
legend_at_bottom=True, rounded_bars=15, explicit_size=True, width=800, height=400)
bar_chart.title = "Playtime in the Last Two Weeks (hours)"

# Add data to the chart
if player_data and "response" in player_data and "games" in player_data["response"]:
for game in player_data["response"]["games"]:
if "name" in game and "playtime_2weeks" in game:
playtime_minutes = game["playtime_2weeks"]
playtime_hours = playtime_minutes / 60 # for plotting

# Determine the label based on the original playtime in minutes
if playtime_minutes >= 60:
# Display in hours if 60 mins or more
label = f"{game["name"]} ({playtime_hours:.2f} hrs)"
else:
# Display in minutes if less than 60
label = f"{game["name"]} ({playtime_minutes} mins)"

# Add to chart using the hours value for consistency in scaling
bar_chart.add(label, playtime_hours)
else:
print("No game data available to display")

# Render the chart to an SVG file
bar_chart.render_to_file("assets/recently_played_games.svg")

return (
"![Steam Games Stats]("
"https://github.com/Nicconike/Steam-Stats/blob/master/assets/recently_played_games.svg"
"?sanitize=true)"
)
# Verify that the environment variables are loaded correctly
if not STEAM_ID:
raise ValueError(
"Missing STEAM_ID in environment variables")


def generate_svg_for_steam_workshop(workshop_stats):
Expand All @@ -62,8 +31,8 @@ def generate_svg_for_steam_workshop(workshop_stats):
}
df = pd.DataFrame(data)
# Generate random colors for each row
colors = [f'rgb({np.random.randint(0, 256)}, {np.random.randint(0, 256)}, {
np.random.randint(0, 256)})' for _ in range(len(df))]
colors = [f"rgb({np.random.randint(0, 256)}, {np.random.randint(0, 256)}, {
np.random.randint(0, 256)})" for _ in range(len(df))]

header = {
"values": header_values,
Expand All @@ -89,7 +58,7 @@ def generate_svg_for_steam_workshop(workshop_stats):
autosize=True,
margin={"pad": 0}
)
fig.write_image("assets/steam_workshop_stats.svg")
fig.write_image("../assets/steam_workshop_stats.svg")

return (
"![Steam Workshop Stats]("
Expand All @@ -98,7 +67,7 @@ def generate_svg_for_steam_workshop(workshop_stats):
)


def update_readme(markdown_data, start_marker, end_marker, readme_path="README.md"):
def update_readme(markdown_data, start_marker, end_marker, readme_path="../README.md"):
"""Updates the README.md file with the provided Markdown content within specified markers."""
# Read the current README content
with open(readme_path, "r", encoding="utf-8") as file:
Expand Down Expand Up @@ -128,16 +97,25 @@ def update_readme(markdown_data, start_marker, end_marker, readme_path="README.m
if __name__ == "__main__":
# Start the timer
start_time = time.time()
player_summary = get_player_summaries()
recently_played_games = get_recently_played_games()
links = fetch_workshop_item_links(STEAM_ID)

USER_MARKDOWN_CONTENT = ""
if recently_played_games:
USER_MARKDOWN_CONTENT += generate_svg_for_recently_played_games(
if player_summary and recently_played_games:
summary_content = generate_card_for_player_summary(player_summary)
recent_games = generate_card_for_played_games(
recently_played_games)
print("Successfully retrieved Steam User Data")

if summary_content and recent_games:
USER_MARKDOWN_CONTENT += summary_content
USER_MARKDOWN_CONTENT += recent_games
print("Successfully retrieved Steam User Data")
else:
print(
"Failed to generate HTML content for Steam Summary or Recently Played Games")
else:
print("Failed to fetch Steam data for Recently Played Games")
print("Failed to fetch Steam Summary & Games Data")

WORKSHOP_MARKDOWN_CONTENT = ""
if links:
Expand All @@ -153,7 +131,7 @@ def update_readme(markdown_data, start_marker, end_marker, readme_path="README.m
"<!-- Steam-Stats start -->", "<!-- Steam-Stats end -->")
update_readme(WORKSHOP_MARKDOWN_CONTENT,
"<!-- Steam-Workshop start -->", "<!-- Steam-Workshop end -->")
print("README.md has been successfully updated.")
print("README.md has been successfully updated")
else:
print("Failed to fetch or process data")

Expand Down
10 changes: 5 additions & 5 deletions api/steam_workshop.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ def fetch_individual_workshop_stats(item_url):
for row in stats_table.find_all("tr"):
cells = row.find_all("td")
if len(cells) == 2:
key = cells[1].text.strip().lower().replace(' ', '_')
value = cells[0].text.strip().replace(',', '')
key = cells[1].text.strip().lower().replace(" ", "_")
value = cells[0].text.strip().replace(",", "")
try:
stats[key] = int(value) if value else 0
except ValueError:
Expand All @@ -119,9 +119,9 @@ def fetch_individual_workshop_stats(item_url):
e}. The structure of the page might have changed")

# Ensure all expected stats are present, even if they are zero
stats['unique_visitors'] = stats.get('unique_visitors', 0)
stats['current_subscribers'] = stats.get('current_subscribers', 0)
stats['current_favorites'] = stats.get('current_favorites', 0)
stats["unique_visitors"] = stats.get("unique_visitors", 0)
stats["current_subscribers"] = stats.get("current_subscribers", 0)
stats["current_favorites"] = stats.get("current_favorites", 0)

return stats

Expand Down
Loading

1 comment on commit 1a91a3c

@vercel
Copy link

@vercel vercel bot commented on 1a91a3c May 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.