Skip to content

Instantly share code, notes, and snippets.

@RikudouSage
Last active March 18, 2025 09:35
Show Gist options
  • Save RikudouSage/8069d322a936a4ab1f254c4ece35a98a to your computer and use it in GitHub Desktop.
Save RikudouSage/8069d322a936a4ab1f254c4ece35a98a to your computer and use it in GitHub Desktop.

Creates a single endpoint: DELETE /delete (with body {"id": 123}). Intended to be used on local network only with the help of Lemmy Webhook and Lemmy Automod.

DO NOT EXPOSE IT TO THE INTERNET

Build:

  1. go mod tidy - initialize dependencies
  2. CGO_ENABLED=0 go build -o lemmy-pm-deleter main.go - build a fully static binary with no dependencies
  3. ./lemmy-pm-deleter - run the server

Docker:

  1. docker build -t lemmy-pm-deleter .

Configuration:

  • APP_PORT - the port to listen on, default: 8080
  • APP_IP - the IP to listen on, default: 127.0.0.1
  • DATABASE_URL - required - in the format postgres://user:password@host:port/database_name
FROM golang:1.24 AS build
WORKDIR /build
COPY . .
RUN go mod tidy && CGO_ENABLED=0 go build -o /app .
FROM alpine:3
ENV APP_IP=0.0.0.0
COPY --from=build /app /app
ENTRYPOINT ["/app"]
module LemmyPmDeleter
go 1.23.0
toolchain go1.23.6
require github.com/jackc/pgx/v5 v5.7.2
require (
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
golang.org/x/crypto v0.36.0 // indirect
golang.org/x/sync v0.12.0 // indirect
golang.org/x/text v0.23.0 // indirect
)
package main
import (
"database/sql"
"encoding/json"
"io"
"log"
"net/http"
"os"
"os/signal"
"strconv"
"syscall"
_ "github.com/jackc/pgx/v5/stdlib"
)
type DeleteRequest struct {
Id int `json:"id"`
}
func getConfig() (port string, ip string, database string) {
port = os.Getenv("APP_PORT")
if port == "" {
port = "8080"
}
ip = os.Getenv("APP_IP")
if ip == "" {
ip = "127.0.0.1"
}
database, ok := syscall.Getenv("DATABASE_URL")
if !ok {
panic("DATABASE_URL not set")
}
return
}
func returnError(err error, writer http.ResponseWriter) {
writer.WriteHeader(http.StatusInternalServerError)
response, _ := json.Marshal(map[string]string{
"error": err.Error(),
})
_, err = writer.Write(response)
if err != nil {
log.Println(err)
}
}
func main() {
gracefulShutdown := make(chan os.Signal, 1)
signal.Notify(gracefulShutdown, syscall.SIGINT, syscall.SIGTERM)
port, ip, database := getConfig()
go func() {
log.Println("Starting server on " + ip + ":" + port)
err := http.ListenAndServe(ip+":"+port, nil)
if err != nil {
panic(err)
}
}()
db, err := sql.Open("pgx", database)
if err != nil {
panic(err)
}
defer db.Close()
log.Println("Connected to database")
http.HandleFunc("DELETE /delete", func(writer http.ResponseWriter, request *http.Request) {
body, err := io.ReadAll(request.Body)
if err != nil {
returnError(err, writer)
return
}
var deleteRequest DeleteRequest
err = json.Unmarshal(body, &deleteRequest)
if err != nil {
returnError(err, writer)
return
}
_, err = db.Exec("delete from private_message where id = $1", deleteRequest.Id)
if err != nil {
log.Println(err)
returnError(err, writer)
} else {
writer.WriteHeader(http.StatusOK)
log.Println("Deleted private message with id " + strconv.Itoa(deleteRequest.Id))
}
})
<-gracefulShutdown
log.Println("Shutting down server...")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment