Skip to content

Commit

Permalink
Update python scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
Nicconike committed Apr 24, 2024
1 parent c72c7b3 commit a34c356
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 51 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/steam-stats.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ name: Steam Stats

on:
schedule:
# Runs on every Sunday midnight IST (UTC+5:30)
- cron: "30 18 * * 6"
# Runs every Monday at 12AM IST (UTC+5:30)
- cron: "30 18 * * 0"
workflow_dispatch:

jobs:
Expand All @@ -17,7 +17,7 @@ jobs:
with:
python-version: '3.x'
- name: Install dependencies
run: pip install requests python-dotenv svgwrite pytz bs4
run: pip install requests python-dotenv pytz bs4 pygal
- name: Update Steam Stats in README
env:
STEAM_API_KEY: ${{ secrets.STEAM_API_KEY }}
Expand Down
18 changes: 1 addition & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,8 @@

<!-- Steam-Stats start -->

## Steam User Summary for Nicco

- **Steam Status:** Offline
- **Last Logoff (IST):** 22/04/2024 03:59:14
- **Profile URL:** [Visit Profile](https://steamcommunity.com/id/nicconike/)
- **Avatar:** ![Avatar](https://avatars.steamstatic.com/d52f6856acfa47d82209d3727dc7ab377d2d639d_medium.jpg)

## Recently Played Games (Total: 4)
- Counter-Strike 2: Playtime last 2 weeks: 3 hrs 59 mins, Total playtime: 3568 hrs 37 mins
- Golf With Your Friends: Playtime last 2 weeks: 1 hrs 22 mins, Total playtime: 7 hrs 55 mins
- PGA TOUR 2K23: Playtime last 2 weeks: 20 mins, Total playtime: 20 mins
- Fallout 76: Playtime last 2 weeks: 10 mins, Total playtime: 1 hrs 39 mins

<!-- Steam-Stats end -->

<!-- Steam-Workshop start -->
<svg baseProfile="full" height="150px" version="1.1" width="300px" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"><![CDATA[
.title { font: bold 20px sans-serif; }
.stat { font: normal 16px sans-serif; }
]]></style></defs><rect fill="white" height="100%" width="100%" x="0" y="0" /><text class="title" x="10" y="30">Steam Workshop Stats</text><text class="stat" x="10" y="60">Total Unique Visitors: 2933</text><text class="stat" x="10" y="80">Total Subscribers: 1770</text><text class="stat" x="10" y="100">Total Favorites: 78</text></svg>

<!-- Steam-Workshop end -->
136 changes: 106 additions & 30 deletions api/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,24 @@
import json
import os
import time
import svgwrite
from steam_stats import get_player_summaries, get_recently_played_games, process_player_summary_data
from steam_workshop import fetch_workshop_item_links, fetch_all_workshop_stats
import pygal

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

# Steam Account Status Mapping
PERSONASTATE_MAPPING = {
0: "Offline",
1: "Online",
2: "Busy",
3: "Away",
4: "Snooze",
5: "Looking to Trade",
6: "Looking to Play"
}


def generate_markdown(summary_data, recently_played_data):
"""Generate combined Markdown content for player data, achievements, recently played games"""
Expand Down Expand Up @@ -62,34 +73,101 @@ def generate_markdown(summary_data, recently_played_data):
return combined_markdown


def generate_svg_card(total_stats):
"""Generates SVG Card for retrieved Workshop Data"""
# def generate_svg_for_steam_summary(player_data):
# """Generates SVG Card for retrieved Steam Summary Data"""
# # Create an SVG drawing instance
# dwg = svgwrite.Drawing(size=('500px', '150px'), profile='full')

# # Set up styles
# styles = """
# .header { font: bold 16px sans-serif; fill: #333; }
# .info { font: 12px sans-serif; fill: #666; }
# """
# dwg.defs.add(dwg.style(styles))

# # Add background
# dwg.add(dwg.rect(insert=(0, 0), size=('100%', '100%'), fill='white'))

# # Add avatar image on the left side
# if 'avatarmedium' in player_data:
# dwg.add(dwg.image(player_data['avatarmedium'], insert=(
# 10, 10), size=('100px', '100px')))

# # Add personaname and hyperlink to profileurl
# if 'personaname' in player_data and 'profileurl' in player_data:
# link = dwg.add(dwg.a(href=player_data['profileurl']))
# link.add(dwg.text(player_data['personaname'], insert=(
# '120px', '30px'), class_='header'))

# # Add personastate and gameextrainfo on the right side
# personastate_text = PERSONASTATE_MAPPING.get(
# player_data.get('personastate', 0), "Unknown")
# dwg.add(dwg.text(f"State: {personastate_text}",
# insert=('120px', '60px'), class_='info'))

# if 'gameextrainfo' in player_data:
# dwg.add(dwg.text(f"Playing: {player_data['gameextrainfo']}", insert=(
# '120px', '80px'), class_='info'))

# # Return SVG content as a string
# return dwg.tostring()

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, show_legend=True)
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 # Convert minutes to hours 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('recently_played_games.svg')

# Optionally, return the SVG data as a string to embed directly in HTML or Markdown
return bar_chart.render(is_unicode=True)


def generate_svg_for_steam_workshop(total_stats):
"""Generates SVG Card for retrieved Workshop Data using Pygal Funnel Chart"""
# Create a Funnel chart instance
funnel_chart = pygal.Funnel(legend_at_bottom=True)
funnel_chart.title = 'Steam Workshop Stats'

# Create an SVG drawing instance
dwg = svgwrite.Drawing(size=('300px', '150px'))
# funnel_chart.x_labels = ['Total Favorites','Total Subscribers', 'Total Unique Visitors']

# Set up styles and background
dwg.add(dwg.rect(insert=(0, 0), size=('100%', '100%'), fill='white'))
styles = """
.title { font: bold 20px sans-serif; }
.stat { font: normal 16px sans-serif; }
"""
dwg.defs.add(dwg.style(styles))
# Add data to the radar chart
funnel_chart.add('Total Subscribers',
total_stats["total_current_subscribers"])
funnel_chart.add('Total Favorites', total_stats["total_current_favorites"])
funnel_chart.add('Total Unique Visitors',
total_stats["total_unique_visitors"])

# Add title and stats
dwg.add(dwg.text("Steam Workshop Stats", insert=(10, 30), class_='title'))
dwg.add(dwg.text(f'Total Unique Visitors: {
total_stats["total_unique_visitors"]}', insert=(10, 60), class_='stat'))
dwg.add(dwg.text(f'Total Subscribers: {
total_stats["total_current_subscribers"]}', insert=(10, 80), class_='stat'))
dwg.add(dwg.text(f'Total Favorites: {
total_stats["total_current_favorites"]}', insert=(10, 100), class_='stat'))
# Render the chart to an SVG file
# funnel_chart.render_to_file('steam_workshop_stats.svg')

# Return SVG content as a string
return dwg.tostring()
# Optionally, return the SVG data as a string to embed directly in HTML or Markdown
return funnel_chart.render(is_unicode=True)


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 @@ -130,15 +208,12 @@ def save_to_file(data, filename):
if __name__ == "__main__":
# Start the timer
start_time = time.time()
player_summary = get_player_summaries()
recently_played_games = get_recently_played_games()

USER_MARKDOWN_CONTENT = ""
if player_summary and recently_played_games and player_summary["response"]["players"]:
steam_player_data = player_summary["response"]["players"][0]
processed_data = process_player_summary_data(steam_player_data)
USER_MARKDOWN_CONTENT += generate_markdown(
processed_data, recently_played_games)
if recently_played_games:
USER_MARKDOWN_CONTENT += generate_svg_for_recently_played_games(
recently_played_games)
print("Successfully retrieved Steam User Data")
else:
print("Failed to fetch steam data")
Expand All @@ -147,7 +222,8 @@ def save_to_file(data, filename):
links = fetch_workshop_item_links(STEAM_ID)
if links:
workshop_data = fetch_all_workshop_stats(links)
WORKSHOP_MARKDOWN_CONTENT = generate_svg_card(workshop_data)
WORKSHOP_MARKDOWN_CONTENT = generate_svg_for_steam_workshop(
workshop_data)
print("Retrieved all workshop stats and created svg")
else:
print("No workshop content was found")
Expand Down
Binary file modified api/requirements.txt
Binary file not shown.
53 changes: 53 additions & 0 deletions api/steam_stats.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"""Retrieves Steam User Data using Steam Web API"""
import json
from zoneinfo import ZoneInfo # Python 3.9 and newer
from datetime import datetime, timezone
import os
import pygal
from dotenv import load_dotenv
import requests

Expand Down Expand Up @@ -84,3 +86,54 @@ def process_player_summary_data(player_data):
"gameid": player_data.get("gameid")
}
return process_data


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, show_legend=True)
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 # Convert minutes to hours 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")

# Return the SVG data as a string to embed directly in Markdown
return bar_chart.render(is_unicode=True)


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")


if __name__ == "__main__":
player_summary = get_player_summaries()
recently_played_games = get_recently_played_games()

generate_svg_for_recently_played_games(recently_played_games)
print(generate_svg_for_recently_played_games)
save_to_file(player_summary, "player_summaries.json")
save_to_file(recently_played_games, "recently_played_games.json")
2 changes: 1 addition & 1 deletion api/steam_workshop.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Scrape Workshop Data and embed it in Readme"""
"""Scrape Steam Workshop Data"""
import requests
from bs4 import BeautifulSoup, Tag

Expand Down
42 changes: 42 additions & 0 deletions api/test_recent_games.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""Testing"""
from steam_stats import get_recently_played_games
import pygal


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, show_legend=True)
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 # Convert minutes to hours 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('recently_played_games.svg')

# Optionally, return the SVG data as a string to embed directly in HTML or Markdown
return bar_chart.render(is_unicode=True)


if __name__ == "__main__":
steam_player_data = get_recently_played_games()
generate_svg_for_recently_played_games(steam_player_data)
58 changes: 58 additions & 0 deletions api/test_workshop.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from steam_workshop import fetch_workshop_item_links, fetch_all_workshop_stats
from main import STEAM_ID
import pygal


def generate_svg_for_steam_workshop(total_stats):
"""Generates SVG Card for retrieved Workshop Data using Pygal Radar Chart"""
# Create a Radar chart instance
radar_chart = pygal.Radar(
fill=True, show_legend=True, legend_at_bottom=True)
radar_chart.title = 'Steam Workshop Stats'

# Define the fields and their respective values

# Set the labels for the axes
radar_chart.x_labels = ['Total Favorites',
'Total Subscribers', 'Total Unique Visitors']

# Add data to the radar chart
radar_chart.add('Total Favorites', total_stats["total_current_favorites"])
radar_chart.add('Total Subscribers',
total_stats["total_current_subscribers"])
radar_chart.add('Total Unique Visitors',
total_stats["total_unique_visitors"])

# Render the chart to an SVG file
radar_chart.render_to_file('steam_workshop_stats.svg')

# Optionally, return the SVG data as a string to embed directly in HTML or Markdown
return radar_chart.render(is_unicode=True)


def generate_svg_for_steam_workshop_funnel(total_stats):
"""Generates SVG Card for retrieved Workshop Data using Pygal Funnel Chart"""
# Create a Funnel chart instance
funnel_chart = pygal.Funnel(legend_at_bottom=True)
funnel_chart.title = 'Steam Workshop Stats'

# funnel_chart.x_labels = ['Total Favorites','Total Subscribers', 'Total Unique Visitors']

# Add data to the radar chart
funnel_chart.add('Total Subscribers',
total_stats["total_current_subscribers"])
funnel_chart.add('Total Favorites', total_stats["total_current_favorites"])
funnel_chart.add('Total Unique Visitors',
total_stats["total_unique_visitors"])

# Render the chart to an SVG file
funnel_chart.render_to_file('steam_workshop_stats.svg')

# Optionally, return the SVG data as a string to embed directly in HTML or Markdown
return funnel_chart.render(is_unicode=True)


if __name__ == "__main__":
links = fetch_workshop_item_links(STEAM_ID)
workshop_data = fetch_all_workshop_stats(links)
generate_svg_for_steam_workshop_funnel(workshop_data)

0 comments on commit a34c356

Please sign in to comment.