Skip to content

Instantly share code, notes, and snippets.

@tolluset
Last active August 19, 2025 10:44
Show Gist options
  • Select an option

  • Save tolluset/a75e7cb594b1f0784df54cfd9ce375cb to your computer and use it in GitHub Desktop.

Select an option

Save tolluset/a75e7cb594b1f0784df54cfd9ce375cb to your computer and use it in GitHub Desktop.
github notifications
package main
import (
"bufio"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"os/exec"
"strings"
"time"
)
type Notification struct {
ID string `json:"id"`
Reason string `json:"reason"`
Subject struct {
Title string `json:"title"`
URL string `json:"url"`
Type string `json:"type"`
} `json:"subject"`
Repository struct {
FullName string `json:"full_name"`
} `json:"repository"`
Unread bool `json:"unread"`
}
func fetchNotifications(token string) {
url := "https://api.github.com/notifications?all=false&participating=true"
req, err := http.NewRequest("GET", url, nil)
if err != nil {
log.Printf("Failed to create request: %v", err)
return
}
// Set authentication headers
req.Header.Set("Authorization", "token "+token)
req.Header.Set("Accept", "application/vnd.github+json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Printf("Request failed: %v", err)
return
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
body, _ := ioutil.ReadAll(resp.Body)
log.Printf("GitHub API error: %s", string(body))
return
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Printf("Failed to read response body: %v", err)
return
}
var notifications []Notification
if err := json.Unmarshal(body, &notifications); err != nil {
log.Printf("Failed to unmarshal JSON: %v", err)
return
}
fmt.Printf("[%s] Unread Notifications:\n", time.Now().Format("2006-01-02 15:04:05"))
if len(notifications) > 0 {
// Play sound if notifications exist
playSound()
for _, n := range notifications {
fmt.Printf("- [%s] %s (%s) in %s\n", n.Subject.Type, n.Subject.Title, n.Subject.URL, n.Repository.FullName)
}
} else {
fmt.Println("No new notifications.")
}
fmt.Println()
}
func playSound() {
// Play sound on macOS
cmd := exec.Command("afplay", "/System/Library/Sounds/Purr.aiff")
err := cmd.Run()
if err != nil {
log.Printf("Failed to play sound: %v", err)
}
}
func loadEnv() {
file, err := os.Open(".env")
if err != nil {
log.Printf("Cannot find .env file: %v", err)
return
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" || strings.HasPrefix(line, "#") {
continue
}
parts := strings.SplitN(line, "=", 2)
if len(parts) == 2 {
key := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
os.Setenv(key, value)
}
}
}
func main() {
// Load .env file
loadEnv()
token := os.Getenv("GITHUB_TOKEN")
if token == "" || token == "your_github_token_here" {
log.Fatal("GITHUB_TOKEN is not set. Please set your token in the .env file.")
}
// Initial execution
fetchNotifications(token)
// Repeat execution every 5 minutes
ticker := time.NewTicker(5 * time.Minute)
defer ticker.Stop()
for {
select {
case <-ticker.C:
fetchNotifications(token)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment