Captain Hook - Web hook server
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

206 lines
4.3 KiB

package main
import (
"database/sql"
"encoding/json"
"fmt"
"html/template"
"log"
"net/http"
"os"
_ "github.com/go-sql-driver/mysql"
)
//Global db object
var db *sql.DB
// Used in writing out errors when they occur
type errorMessage struct {
StatusCode int
Msg string
}
// Writes the given error message in the template. If not, just writes the message raw
func writeError(w http.ResponseWriter, e errorMessage) {
// Try to use error template
w.WriteHeader(e.StatusCode)
t := template.Must(template.New("error.html").ParseFiles("html/error.html"))
err := t.Execute(w, e)
// If something goes wrong just tell them the error in an ugly way
if err != nil {
// Can't tell the user since the writer already wrote out
log.Println(err)
}
}
// Get all the currently available hooks
func getHooks(w http.ResponseWriter) []Hook {
// Get all hooks from db
rows, err := db.Query("SELECT ID FROM Hooks")
if err != nil {
logError(w, err)
}
defer rows.Close()
// Look through hooks
hooks := make([]Hook, 0)
for rows.Next() {
var hook Hook
err = rows.Scan(&hook.Name)
// Hook doesn't have a name (This shouldn't really happen)
if err != nil {
logError(w, err)
}
hooks = append(hooks, hook)
}
return hooks
}
// Run a particular hook (will probably come up with a better solution)
func runHook(w http.ResponseWriter, r *http.Request, hook Hook) {
b, err := json.Marshal(hook)
if err != nil {
logError(w, err)
} else {
fmt.Fprint(w, string(b))
}
}
// Show the index
func index(w http.ResponseWriter, r *http.Request) {
// Log request to this url
log.Println(r.URL.String(), r.Method)
if r.URL.String() == "/" {
// Serve index template
t := template.Must(template.New("index.html").ParseFiles("html/index.html"))
err := t.Execute(w, getHooks(w))
if err != nil {
logError(w, err)
}
// Can't find the page
} else {
writeError(w, errorMessage{
StatusCode: http.StatusNotFound,
Msg: "Not Found",
})
}
}
// Handles requests to /hook/
func hookHandler(w http.ResponseWriter, r *http.Request) {
// Log request to this url
log.Println(r.URL.String(), r.Method)
if r.URL.String() == "/hook/" {
switch r.Method {
// Display all hooks
case http.MethodGet:
showHooks(w)
// Method unsupported
default:
log.Println("y tho")
writeError(w, errorMessage{
StatusCode: http.StatusMethodNotAllowed,
Msg: "Method Unsupported",
})
}
return
}
// Hook name
name := r.URL.String()[len("/hook/"):]
switch r.Method {
// Handle the hook
case http.MethodGet, http.MethodPost:
// See if the hook exists
row := db.QueryRow("SELECT EXISTS(SELECT id FROM Hooks WHERE Hooks.id = ?)", name)
var res int
row.Scan(&res)
// Hook doesn't exist
if res == 0 {
writeError(w, errorMessage{
StatusCode: http.StatusNotFound,
Msg: "Not Found",
})
return
}
// Construct the hook from the results
hook := Hook{
Name: name,
conditions: nil,
}
// Run the user's hook
runHook(w, r, hook)
// Create / Update the hook
case http.MethodPut:
createHook(w, name)
// Delete the hook
case http.MethodDelete:
deleteHook(w, name)
// Method unsupported
default:
writeError(w, errorMessage{
StatusCode: http.StatusMethodNotAllowed,
Msg: "Method Not Allowed",
})
}
}
// Shows all of the hooks
func showHooks(w http.ResponseWriter) {
hooks := getHooks(w)
b, err := json.Marshal(hooks)
if err != nil {
logError(w, err)
} else {
fmt.Fprint(w, string(b))
}
}
// Creates a new hook
func createHook(w http.ResponseWriter, name string) {
statement, err := db.Prepare("INSERT IGNORE INTO Hooks(id) VALUES(?)")
// Shouldn't really happen, but incase the insert goes wrong
if err != nil {
logError(w, err)
os.Exit(1)
return
}
defer statement.Close()
statement.Exec(name)
fmt.Fprintln(w, name)
}
// Delete a hook
func deleteHook(w http.ResponseWriter, name string) {
statement, err := db.Prepare("DELETE FROM Hooks WHERE ID=(?)")
//Shouldn't ever error
if err != nil {
logError(w, err)
return
}
defer statement.Close()
// Get results
res, err := statement.Exec(name)
// Shouldn't ever error
if err != nil {
logError(w, err)
return
}
// Probably also shouldn't error
_, err = res.RowsAffected()
if err != nil {
logError(w, err)
return
}
fmt.Fprintln(w, name)
}