Never miss important website changes again!
UpToDate monitors websites and notifies you when specific content appears or disappears. Perfect for tracking price drops, stock availability, news alerts, or any content that matters to you.
- ποΈ Price Monitoring - Get notified when prices drop or sales start
- π¦ Stock Alerts - Know instantly when items come back in stock
- π° News Tracking - Stay updated on breaking news or specific topics
- π¨ Service Monitoring - Monitor API health, error rates, or uptime
- π Content Changes - Track any text, numbers, or patterns on websites
- Smart Pattern Matching - Find exact text, use regex, or combine multiple conditions
- Multiple Notifications - Email, Discord, and Slack alerts
- Real Browser Engine - Handles JavaScript and dynamic content perfectly
- Flexible Scheduling - Check every minute or once a day
- XPath Support - Target specific page elements precisely
- Docker Ready - Easy deployment with Docker Compose
# Download the binary or build from source
go mod tidy
go build -o uptodateCreate a config.json file:
{
"url": "https://example-store.com/product/123",
"search": {
"type": "string",
"pattern": "In Stock",
"notify_on": "found"
},
"notifications": {
"discord": {
"webhook_url": "https://discord.com/api/webhooks/YOUR_WEBHOOK_URL"
}
},
"interval": 300
}# Using the binary
./uptodate -config config.json
# Using docker compose
docker compose up -dThat's it! You'll get notified on Discord when "In Stock" appears on the page.
Monitors a product page and sends email alerts when the price drops to $10-$49 range.
{
"url": "https://store.com/expensive-item",
"search": {
"type": "regex",
"pattern": "\\$[1-4][0-9]\\.[0-9]{2}",
"xpath": "//div[@class='price']",
"notify_on": "found"
},
"notifications": {
"email": {
"smtp_host": "smtp.gmail.com",
"smtp_port": 587,
"username": "your-email@gmail.com",
"password": "your-app-password",
"from": "your-email@gmail.com",
"to": "alerts@example.com",
"subject": "π° Price Drop Alert!"
}
},
"interval": 600
}Watches a news site and sends Slack alerts when breaking news articles with dates are published.
{
"url": "https://news-site.com",
"search": {
"type": "compound",
"pattern": "string:'breaking news' AND regex:[0-9]{4}-[0-9]{2}-[0-9]{2}",
"notify_on": "found"
},
"notifications": {
"slack": {
"webhook_url": "YOUR_SLACK_WEBHOOK"
}
},
"interval": 60
}Monitors an API health endpoint and sends alerts to Discord and email when the service becomes unhealthy.
{
"url": "https://api.yourservice.com/health",
"search": {
"type": "string",
"pattern": "healthy",
"notify_on": "not_found"
},
"notifications": {
"discord": {
"webhook_url": "YOUR_DISCORD_WEBHOOK"
},
"email": {
"smtp_host": "smtp.gmail.com",
"smtp_port": 587,
"username": "monitoring@company.com",
"password": "password",
"from": "monitoring@company.com",
"to": "devops@company.com",
"subject": "π¨ Service Down!"
}
},
"interval": 120
}url- The webpage to monitorsearch.pattern- What to look for on the pagenotifications- At least one notification method (email, discord, or slack)
search.type-"string"(exact text),"regex"(pattern), or"compound"(multiple conditions)search.notify_on-"found"(notify when pattern is found) or"not_found"(notify when pattern is not found)search.xpath- Optional: target specific page elements (e.g.,"//div[@class='price']")
interval- How often to check in seconds (default: 300 = 5 minutes)
Works with most common email providers (Gmail, Hotmail, ...):
"email": {
"smtp_host": "smtp.gmail.com",
"smtp_port": 587,
"username": "your-email@gmail.com",
"password": "your-app-password",
"from": "your-email@gmail.com",
"to": "alerts@example.com",
"subject": "UpToDate Alert"
}Gmail Setup:
- Enable 2-factor authentication
- Generate an "App Password"
- Use the app password instead of your regular password
- Go to your Discord server
- Server Settings β Integrations β Webhooks
- Create webhook and copy the URL
"discord": {
"webhook_url": "https://discord.com/api/webhooks/YOUR_WEBHOOK_URL"
}- Create a Slack app
- Add "Incoming Webhooks" feature
- Copy the webhook URL
"slack": {
"webhook_url": "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK"
}"search": {
"type": "string",
"pattern": "Sale"
}"search": {
"type": "regex",
"pattern": "\\$[0-9]+\\.[0-9]{2}"
}Use AND and OR to combine multiple conditions:
"search": {
"type": "compound",
"pattern": "string:'price drop' AND regex:\\$[0-9]+\\.[0-9]{2}"
}Compound Pattern Examples:
"string:sale OR string:discount"- Either word appears"string:'breaking news' AND regex:[0-9]{4}"- Both conditions must be true"(string:error OR string:failed) AND regex:[0-9]{2}:[0-9]{2}"- Use parentheses for grouping
Important: Use single quotes for text containing spaces or special characters: string:'Hot Deal'
Target specific page elements:
"search": {
"type": "string",
"pattern": "In Stock",
"xpath": "//div[@class='availability']"
}Common XPath examples:
"//div[@class='price']"- Element with specific class"//span[@id='stock-status']"- Element with specific ID"//h1"- All H1 headings"//div[contains(@class, 'product')]"- Class contains text
# Continuous monitoring (default)
./uptodate -config config.json
# Run once and exit
./uptodate -config config.json -once
# Use different config file
./uptodate -config /path/to/my-config.json# Using docker-compose
docker compose up -d"Pattern not found" but you can see it on the page
- The content might be lazy loaded by JavaScript - Currently this is not handled, feel free to create an issue.
- Check if the text is in a specific element using XPath
- Verify the exact text (case-sensitive)
Getting too many notifications
- Increase the
interval(time between checks) - Make your pattern more specific
- Use XPath to target a specific page section
Pattern syntax errors
- Use single quotes for text with spaces, AND/OR or special characters:
string:'hello world' - Escape special regex characters:
\\$for dollar signs - Check parentheses are balanced in compound patterns
UpToDate uses a modular architecture:
- Browser Engine: go-rod with embedded Chromium for JavaScript support
- Pattern Parser: Recursive descent parser for compound patterns
- Notification System: Plugin-style support for multiple channels
- Configuration: JSON-based with validation
git clone https://github.com/paul-eff/UpToDate
cd UpToDate
go mod tidy
go build -o uptodateβββ main.go # Application entry point
βββ config.go # Configuration parsing & compound patterns
βββ browser.go # Browser-based web fetching
βββ client.go # Client interface
βββ notifications.go # Multi-channel notification system
βββ examples/ # Configuration examples
- Add config struct to
config.go:
type MyServiceConfig struct {
APIKey string `json:"api_key"`
Channel string `json:"channel"`
}- Add to main Notifications struct:
type Notifications struct {
Email *EmailConfig `json:"email,omitempty"`
Discord *DiscordConfig `json:"discord,omitempty"`
Slack *SlackConfig `json:"slack,omitempty"`
MyService *MyServiceConfig `json:"myservice,omitempty"`
}- Implement sending in
notifications.go:
func (ns *NotificationService) sendMyService(message string) error {
// Implementation here
}The compound pattern parser uses recursive descent parsing:
- Tokenization: Handles quoted strings and operators
- Precedence: AND has higher precedence than OR
- Quotes: Single quotes preferred (no JSON escaping needed)
- Evaluation: Returns boolean result and matched strings
All configuration is validated at startup:
- Required fields checked
- Pattern syntax validated
- Notification channels verified
- Defaults applied where appropriate
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
This project is licensed under the MIT License.
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
If UpToDate helps you catch that perfect deal or stay informed, please consider giving it a star!