Skill: patfitzner/upcoming-concerts (version 1.0.0)

--- name: upcoming-concerts description: Search for upcoming concerts and live music events by city, country, artist, or genre using the Ticketmaster Discovery API. Use when the user asks about upcoming shows, concerts, gigs, or events in a city or for an artist. metadata: {"openclaw":{"emoji":"🎸","requires":{"bins":["python3"],"env":["TICKETMASTER_API_KEY"]},"primaryEnv":"TICKETMASTER_API_KEY"}} --- # Upcoming Events Search for upcoming concerts and live music events worldwide via the Ticketmaster Discovery API. ## Usage ```bash python3 {baseDir}/events.py --city "Valencia" --country ES ``` ## Command Options - `--city` (optional): City name (e.g. "Valencia", "Berlin", "New York") - `--country` (optional): ISO 3166-1 alpha-2 country code (e.g. ES, DE, US, GB) - `--artist` (optional): Filter by artist/keyword in event name - `--genre` (optional): Genre filter (e.g. "Metal", "Rock", "Jazz", "Pop") - `--from` (optional): Start date in YYYY-MM-DD format (default: today) - `--to` (optional): End date in YYYY-MM-DD format (default: 1 year from today) - `--size` (optional): Max number of results (default: 50, max: 200) ## Examples ```bash # All upcoming concerts in Valencia, Spain python3 {baseDir}/events.py --city "Valencia" --country ES # Metal shows in Germany python3 {baseDir}/events.py --country DE --genre "Metal" # Specific artist events worldwide python3 {baseDir}/events.py --artist "Metallica" # Rock concerts in London this summer python3 {baseDir}/events.py --city "London" --country GB --genre "Rock" --from 2026-06-01 --to 2026-08-31 ``` ## Output The script prints a JSON array to stdout. Each entry contains: - `date`: Event date (YYYY-MM-DD) - `name`: Event name - `artists`: List of performing artist names - `venue`: Venue name - `city`: City name - `country`: Country code - `genre`: Genre/subgenre if available - `url`: Ticketmaster event URL Present the results to the user as a readable table sorted by date. ## Setup The user needs a free Ticketmaster API key: 1. Sign up at https://developer.ticketmaster.com/ 2. Copy the Consumer Key from the dashboard 3. Set it: `export TICKETMASTER_API_KEY="your_key_here"`

path: README.md
content: # upcoming-events

OpenClaw skill to search for upcoming concerts and live music events worldwide using the Ticketmaster Discovery API.

## Setup

1. Get a free API key at https://developer.ticketmaster.com/
2. Set the environment variable:
   ```bash
   export TICKETMASTER_API_KEY="your_key_here"
   ```

## Install

Copy this directory into `~/.openclaw/skills/upcoming-events/` or your workspace `skills/` folder.

## Standalone usage

```bash
python3 events.py --city "Valencia" --country ES
python3 events.py --country DE --genre "Metal"
python3 events.py --artist "Metallica"
```


path: events.py
content: #!/usr/bin/env python3
"""Query upcoming concerts/events from the Ticketmaster Discovery API."""

import argparse
import json
import os
import sys
import urllib.request
import urllib.parse
from datetime import datetime, timedelta

API_BASE = "https://app.ticketmaster.com/discovery/v2/events.json"


def fetch_events(params: dict) -> list[dict]:
    query = urllib.parse.urlencode(params)
    url = f"{API_BASE}?{query}"
    req = urllib.request.Request(url, headers={"Accept": "application/json"})
    with urllib.request.urlopen(req) as resp:
        data = json.loads(resp.read())

    if "_embedded" not in data:
        return []

    results = []
    seen = set()
    for event in data["_embedded"]["events"]:
        venues = event.get("_embedded", {}).get("venues", [])
        venue = venues[0] if venues else {}
        artists = [
            a["name"]
            for a in event.get("_embedded", {}).get("attractions", [])
        ]

        date = event.get("dates", {}).get("start", {}).get("localDate", "")
        name = event.get("name", "")
        venue_name = venue.get("name", "")

        dedup_key = (date, name, venue_name)
        if dedup_key in seen:
            continue
        seen.add(dedup_key)

        classifications = event.get("classifications", [{}])
        genre_info = classifications[0] if classifications else {}

        results.append({
            "date": date,
            "name": name,
            "artists": artists,
            "venue": venue_name,
            "city": venue.get("city", {}).get("name", ""),
            "country": venue.get("country", {}).get("countryCode", ""),
            "genre": genre_info.get("genre", {}).get("name", ""),
            "url": event.get("url", ""),
        })

    results.sort(key=lambda e: e["date"])
    return results


def main():
    parser = argparse.ArgumentParser(description="Search upcoming events")
    parser.add_argument("--city", help="City name")
    parser.add_argument("--country", help="ISO country code (e.g. ES, US, GB)")
    parser.add_argument("--artist", help="Artist or keyword filter")
    parser.add_argument("--genre", help="Genre (e.g. Metal, Rock, Jazz)")
    parser.add_argument("--from", dest="date_from", help="Start date (YYYY-MM-DD)")
    parser.add_argument("--to", dest="date_to", help="End date (YYYY-MM-DD)")
    parser.add_argument("--size", type=int, default=50, help="Max results (default 50)")
    args = parser.parse_args()

    [REDACTED_SECRET]"TICKETMASTER_API_KEY")
    if not [REDACTED_SECRET]"Error: TICKETMASTER_API_KEY environment variable not set.", file=sys.stderr)
        print("Get a free key at https://developer.ticketmaster.com/", file=sys.stderr)
        sys.exit(1)

    date_from = args.date_from or datetime.now().strftime("%Y-%m-%d")
    date_to = args.date_to or (datetime.now() + timedelta(days=365)).strftime("%Y-%m-%d")

    params = {
        "apikey": api_key,
        "classificationName": "music",
        "startDateTime": f"{date_from}T00:00:00Z",
        "endDateTime": f"{date_to}T23:59:59Z",
        "size": min(args.size, 200),
        "sort": "date,asc",
    }

    if args.city:
        params["city"] = args.city
    if args.country:
        params["countryCode"] = args.country
    if args.artist:
        params["keyword"] = args.artist
    if args.genre:
        params["classificationName"] = args.genre

    try:
        results = fetch_events(params)
    except urllib.error.HTTPError as e:
        body = e.read().decode()
        print(f"Error: API returned {e.code}: {body}", file=sys.stderr)
        sys.exit(1)

    json.dump(results, sys.stdout, indent=2, ensure_ascii=False)
    print()


if __name__ == "__main__":
    main()


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)