
Game News
- 1 installs
- Updated April 24, 2026
- cyberpunk89/hermes-discord-bot
Helps with ai & agent building tasks.
About
game-news is a Claude Code skill for ai & agent building. It helps developers move faster with AI-assisted coding.
- game-news
- AI & Agent Building
- AI-coding skill
Game News by the numbers
- 1 all-time installs (skills.sh)
- Ranked #14,102 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Jul 7, 2026 (Skillselion catalog sync)
npx skills add https://github.com/cyberpunk89/hermes-discord-bot --skill game-newsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1 |
|---|---|
| Last updated | April 24, 2026 |
| Repository | cyberpunk89/hermes-discord-bot ↗ |
What it does
Helps with ai & agent building tasks.
Files
Game News Fetcher
MANDATORY — DO NOT SKIP
YOU MUST RUN THE SCRIPT FIRST. This is not optional.
1. Run the terminal command BEFORE responding 2. The script output MUST appear in your response 3. DO NOT make up patch notes — use ONLY script output 4. If the script fails, state the error clearly
Failure to run the script will result in incorrect responses.
IMPORTANT
Run the terminal command immediately. Do not make up patch notes. Do not print or echo the terminal command in your response.
Command
When a user manually asks for game news — use --recent so browsing doesn't consume the cron feed:
python3 /home/nikel/Documents/projects/discord/game-price-bot/skills/game-news/scripts/news_fetcher.py --recentFor a specific game (manual, by Steam app ID):
python3 /home/nikel/Documents/projects/discord/game-price-bot/skills/game-news/scripts/news_fetcher.py --recent <app_id>When invoked by cron — omit --recent so items are marked seen and won't re-post:
python3 /home/nikel/Documents/projects/discord/game-price-bot/skills/game-news/scripts/news_fetcher.pyOutput Interpretation
NEW_ITEMS: 0— nothing new; say "the realm is quiet"NEW_ITEMS: <n>— items follow, separated by---- Each item:
GAME,TITLE,URL,DATE,SUMMARY
Response Style
Use this exact format for each item, with a blank line between items:
**{GAME}** — {TITLE}
{1–2 sentences in Hermes character summarising what changed}
{DATE} · <{URL}>Tone by update type:
- Patch / hotfix → dry, matter-of-fact with one cutting remark ("The gods corrected their error. It took them three weeks.")
- Major update / new content → excited herald energy, one punchy line of hype
- Event / season → treat as political intrigue from Olympus
If there are multiple items for the same game, group them together under one game header rather than repeating the name.
Never paste bare URLs — always wrap in angle brackets: <https://example.com>.
#!/usr/bin/env python3
import sys
import os
import re
import requests
from datetime import datetime
# Import centralized utilities
_PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
sys.path.insert(0, _PROJECT_DIR)
sys.path.insert(0, os.path.join(_PROJECT_DIR, "skills"))
sys.path.insert(0, os.path.join(_PROJECT_DIR, "db"))
import _importer # noqa: F401
import _load_env # noqa: F401
from _rate_limiter import STEAM_LIMITER
from database import get_common_games, is_news_seen, add_seen_news
from cache import get_cache, set_cache
STEAM_NEWS_URL = "https://api.steampowered.com/ISteamNews/GetNewsForApp/v2/"
UPDATE_KEYWORDS = {"update", "patch", "hotfix", "new content", "season", "event", "dlc", "release"}
# News cache TTL: 4 hours
NEWS_CACHE_TTL = 4 * 3600
_HTML_TAG = re.compile(r"<[^>]+>")
_BBCODE_TAG = re.compile(r"\[/?[a-z*]+(?:=[^\]]+)?\]", re.IGNORECASE)
_WHITESPACE = re.compile(r"\s+")
_HTML_ENTITIES = {"&": "&", "<": "<", ">": ">", """: '"', "'": "'", " ": " "}
def clean_summary(text, max_len=250):
for entity, char in _HTML_ENTITIES.items():
text = text.replace(entity, char)
text = _HTML_TAG.sub(" ", text)
text = _BBCODE_TAG.sub(" ", text)
text = _WHITESPACE.sub(" ", text).strip()
if len(text) <= max_len:
return text
cut = text.rfind(" ", 0, max_len)
return text[:cut if cut > 0 else max_len] + "…"
def is_relevant(title, contents):
text = (title + " " + contents).lower()
return any(kw in text for kw in UPDATE_KEYWORDS)
def fetch_news(app_id, game_name, recent_mode=False):
try:
# Rate limit before API call
STEAM_LIMITER.wait()
r = requests.get(
STEAM_NEWS_URL,
params={"appid": app_id, "count": 10, "maxlength": 500, "format": "json"},
timeout=10,
)
items = r.json().get("appnews", {}).get("newsitems", [])
results = []
for item in items:
gid = item.get("gid", "")
title = item.get("title", "")
contents = item.get("contents", "")
url = item.get("url", "")
date = datetime.fromtimestamp(item.get("date", 0)).strftime("%Y-%m-%d")
if not is_relevant(title, contents):
continue
if not recent_mode:
if is_news_seen(gid):
continue
add_seen_news(app_id, gid, title)
results.append({"game": game_name, "title": title, "url": url, "date": date, "summary": clean_summary(contents)})
if recent_mode and len(results) >= 3:
break
return results
except Exception:
return []
def main():
args = sys.argv[1:]
recent_mode = "--recent" in args
args = [a for a in args if a != "--recent"]
if args:
app_id = int(args[0])
games = [{"app_id": app_id, "game_name": f"App {app_id}"}]
else:
games = get_common_games()
if not games:
print("NEW_ITEMS: 0")
return
all_items = []
for game in games:
items = fetch_news(game["app_id"], game["game_name"], recent_mode=recent_mode)
all_items.extend(items)
print(f"NEW_ITEMS: {len(all_items)}")
for item in all_items:
print("---")
print(f"GAME: {item['game']}")
print(f"TITLE: {item['title']}")
print(f"URL: {item['url']}")
print(f"DATE: {item['date']}")
print(f"SUMMARY: {item['summary']}")
if __name__ == "__main__":
main()