Skip to content

Instantly share code, notes, and snippets.

@suntong
Created September 2, 2024 15:08
Show Gist options
  • Save suntong/d3203029f4dd088e3b5ed2b0aaee652c to your computer and use it in GitHub Desktop.
Save suntong/d3203029f4dd088e3b5ed2b0aaee652c to your computer and use it in GitHub Desktop.
gistpost create
////////////////////////////////////////////////////////////////////////////
// Program: gistpost
// Purpose: GH gist post/update tool
// Authors: Tong Sun (c) 2024-2024, All rights reserved
////////////////////////////////////////////////////////////////////////////
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"time"
)
////////////////////////////////////////////////////////////////////////////
// Constant and data type/structure definitions
type gistFile struct {
Content string `json:"content"`
}
type gist struct {
Description string `json:"description"`
Public bool `json:"public"`
Files map[string]gistFile `json:"files"`
}
////////////////////////////////////////////////////////////////////////////
// Global variables definitions
////////////////////////////////////////////////////////////////////////////
// Function definitions
func optsCheck() {
// == Sanity check on variables from environment
if opts.Token == "" {
gfParser.WriteHelp(os.Stdout)
fmt.Println("\nError: The GISTPOST_TOKEN environment variable is required")
os.Exit(1)
}
if opts.Description == "" {
t := time.Now()
opts.Description = "Archived on " + t.Format(time.DateOnly)
}
if opts.Filename == "" {
opts.Filename = "archive.md"
}
// == Sanity check on stdin
// Get file information about stdin
info, err := os.Stdin.Stat()
if err != nil {
fmt.Println("Error checking stdin:", err)
os.Exit(1)
}
// Check if stdin is from a pipe
if info.Mode()&os.ModeCharDevice != 0 {
gfParser.WriteHelp(os.Stdout)
fmt.Println("\nError: This program reads input from pipe.")
os.Exit(1)
}
}
// // Exec implements the business logic of command `create`
func (x *CreateCommand) Exec(args []string) error {
// err := ...
// clis.WarnOn("create::Exec", err)
// or,
// clis.AbortOn("create::Exec", err)
optsCheck()
// }
// func (x *CreateCommand) Exec(args []string) error {
// Read content from stdin
content, err := ioutil.ReadAll(os.Stdin)
if err != nil {
log.Fatalf("Error reading stdin: %v", err)
}
if opts.Wrap {
content = []byte("```\n" + string(content) + "\n```\n")
}
// Create the gist
gist := gist{
Description: opts.Description,
Public: x.Public,
Files: map[string]gistFile{
opts.Filename: {Content: string(content)},
},
}
// Convert gist to JSON
gistJson, err := json.Marshal(gist)
if err != nil {
log.Fatalf("Error marshaling Gist JSON: %v", err)
}
// Make the POST request to GitHub Gist API
client := &http.Client{}
req, err := http.NewRequest("POST", "https://api.github.com/gists", bytes.NewBuffer(gistJson))
if err != nil {
log.Fatalf("Error creating POST request: %v", err)
}
req.Header.Set("Authorization", "token "+opts.Token)
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
log.Fatalf("Error posting to GitHub Gist: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusCreated {
log.Fatalf("Failed to create gist, status: %s", resp.Status)
}
// Print the URL of the created gist
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
fmt.Println("Gist created: ", result["html_url"])
return nil
}
//==========================================================================
// support functions
/*
Usage example:
export GP_GIST_T_TOKEN=github_pat_...
$ cat gistpost_main.go | gistpost -d 'gistpost main' -f main.go -p
Gist created: https://gist.github.com/suntong/923dabcb17c73e7ba435c0067eee3b19
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment