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.

245 lines
6.0 KiB

  1. package main
  2. import (
  3. "encoding/json"
  4. "io/ioutil"
  5. "log"
  6. "net/http"
  7. "os"
  8. "strconv"
  9. "bytes"
  10. rice "github.com/GeertJohan/go.rice"
  11. "github.com/campoy/svg-badge/badge"
  12. "github.com/joho/godotenv"
  13. stripe "github.com/stripe/stripe-go/v72"
  14. "github.com/stripe/stripe-go/v72/paymentintent"
  15. "golang.org/x/image/font/gofont/goregular"
  16. )
  17. func loadEnv() {
  18. err := godotenv.Load()
  19. if err != nil {
  20. log.Fatal("Error loading .env file")
  21. }
  22. }
  23. func stripeConfigHandler(w http.ResponseWriter, r *http.Request) {
  24. type Config struct {
  25. StripePK string
  26. StripeACC string
  27. StripeApiVersion string
  28. StripeLocale string
  29. }
  30. switch r.Method {
  31. case http.MethodGet:
  32. config := Config{
  33. os.Getenv("STRIPE_PK"),
  34. os.Getenv("STRIPE_ACC"),
  35. os.Getenv("STRIPE_API_VERSION"),
  36. os.Getenv("STRIPE_LOCALE"),
  37. }
  38. // log.Fatal(configJson)
  39. w.Header().Set("Content-Type", "application/json")
  40. w.WriteHeader(http.StatusOK)
  41. json.NewEncoder(w).Encode(config)
  42. default:
  43. http.Error(w, "This endpoint only supports GET requrests.", http.StatusMethodNotAllowed)
  44. return
  45. }
  46. }
  47. func configHandler(w http.ResponseWriter, r *http.Request) {
  48. type Config struct {
  49. MetaTitle string
  50. Title string
  51. Description string
  52. DefaultCurrency string
  53. BackLink string
  54. EmailLink string
  55. GitLink string
  56. GithubLink string
  57. GitlabLink string
  58. FacebookLink string
  59. TwitterLink string
  60. InstagramLink string
  61. LinkedinLink string
  62. BGColor string
  63. TextColor string
  64. ButtonColor string
  65. TopNavColor string
  66. BGColorDark string
  67. TextColorDark string
  68. ButtonColorDark string
  69. TopNavColorDark string
  70. }
  71. switch r.Method {
  72. case http.MethodGet:
  73. config := Config{
  74. os.Getenv("META_TITLE"),
  75. os.Getenv("TITLE"),
  76. os.Getenv("DESCRIPTION"),
  77. os.Getenv("DEFAULT_CURRENCY"),
  78. os.Getenv("BACK_LINK"),
  79. os.Getenv("EMAIL_LINK"),
  80. os.Getenv("GIT_LINK"),
  81. os.Getenv("GITHUB_LINK"),
  82. os.Getenv("GITLAB_LINK"),
  83. os.Getenv("FACEBOOK_LINK"),
  84. os.Getenv("TWITTER_LINK"),
  85. os.Getenv("INSTAGRAM_LINK"),
  86. os.Getenv("LINKEDIN_LINK"),
  87. os.Getenv("BG_COLOR"),
  88. os.Getenv("TEXT_COLOR"),
  89. os.Getenv("BUTTON_COLOR"),
  90. os.Getenv("TOP_NAV_COLOR"),
  91. os.Getenv("BG_COLOR_DARK"),
  92. os.Getenv("TEXT_COLOR_DARK"),
  93. os.Getenv("BUTTON_COLOR_DARK"),
  94. os.Getenv("TOP_NAV_COLOR_DARK"),
  95. }
  96. // log.Fatal(configJson)
  97. w.Header().Set("Content-Type", "application/json")
  98. w.WriteHeader(http.StatusOK)
  99. json.NewEncoder(w).Encode(config)
  100. default:
  101. http.Error(w, "This endpoint only supports GET requrests.", http.StatusMethodNotAllowed)
  102. return
  103. }
  104. }
  105. func sendOwncastNotification(message string) {
  106. type ReqBody struct {
  107. Body string `json:"body"`
  108. }
  109. if os.Getenv("OWNCAST_HOSTNAME") != "" {
  110. reqUrl := "https://" + os.Getenv("OWNCAST_HOSTNAME") + "/api/integrations/chat/system"
  111. // Create a Bearer string by appending string access token
  112. var bearer = "Bearer " + os.Getenv("OWNCAST_TOKEN")
  113. ownCastBody := &ReqBody{
  114. Body: message,
  115. }
  116. payloadBuf := new(bytes.Buffer)
  117. json.NewEncoder(payloadBuf).Encode(ownCastBody)
  118. // Create a new request using http
  119. req, err := http.NewRequest(http.MethodPost, reqUrl, payloadBuf)
  120. // add authorization header to the req
  121. req.Header.Add("Authorization", bearer)
  122. req.Header.Set("Content-Type", "application/json")
  123. // Send req using http Client
  124. client := &http.Client{}
  125. resp, err := client.Do(req)
  126. if err != nil {
  127. log.Println("Error on response.\n[ERROR] -", err)
  128. }
  129. defer resp.Body.Close()
  130. body, err := ioutil.ReadAll(resp.Body)
  131. if err != nil {
  132. log.Println("Error while reading the response bytes:", err)
  133. }
  134. log.Println(string([]byte(body)))
  135. log.Println(resp)
  136. }
  137. }
  138. func getSecretHandler(w http.ResponseWriter, r *http.Request) {
  139. switch r.Method {
  140. case http.MethodPost:
  141. type LineItems struct {
  142. Amount int64
  143. Currency string
  144. Description string
  145. }
  146. type CheckoutData struct {
  147. ClientSecret string `json:"client_secret"`
  148. }
  149. type Response struct {
  150. SessionID string
  151. StripePK string
  152. }
  153. var items LineItems
  154. _ = json.NewDecoder(r.Body).Decode(&items)
  155. params := &stripe.PaymentIntentParams{
  156. Amount: stripe.Int64(items.Amount),
  157. Currency: stripe.String(items.Currency),
  158. Description: stripe.String(items.Description),
  159. }
  160. intent, _ := paymentintent.New(params)
  161. data := CheckoutData{
  162. ClientSecret: intent.ClientSecret,
  163. }
  164. sendOwncastNotification("Donation of " + strconv.FormatInt(items.Amount / 100, 10) + items.Currency + ". Message: " + items.Description)
  165. w.Header().Set("Content-Type", "application/json")
  166. w.WriteHeader(http.StatusOK)
  167. json.NewEncoder(w).Encode(data)
  168. default:
  169. http.Error(w, "This endpoint only supports POST requrests.", http.StatusMethodNotAllowed)
  170. return
  171. }
  172. }
  173. func badgeHandler(w http.ResponseWriter, r *http.Request) {
  174. m, err := badge.NewMaker("Go Regular", goregular.TTF)
  175. if err != nil {
  176. log.Fatal(err)
  177. }
  178. badgeFontSize, err := strconv.ParseFloat(os.Getenv("BADGE_FONT_SIZE"), 32)
  179. badgeHeight, err := strconv.Atoi(os.Getenv("BADGE_HEIGHT"))
  180. b, err := m.New("EL", os.Getenv("BADGE_TEXT"), os.Getenv("BADGE_COLOR"), badgeFontSize, badgeHeight)
  181. if err != nil {
  182. log.Fatal(err)
  183. }
  184. w.Header().Set("Content-Type", "image/svg+xml; charset=utf-8")
  185. w.WriteHeader(http.StatusOK)
  186. w.Write(b)
  187. }
  188. func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
  189. w.WriteHeader(http.StatusOK)
  190. w.Write([]byte("Health Check"))
  191. }
  192. func main() {
  193. loadEnv()
  194. stripe.Key = os.Getenv("STRIPE_SK")
  195. assets := http.FileServer(http.Dir("./"))
  196. http.Handle("/", http.FileServer(rice.MustFindBox("frontend/dist").HTTPBox()))
  197. http.Handle("/assets/", assets)
  198. http.HandleFunc("/api/site/config", configHandler)
  199. http.HandleFunc("/api/pay/config", stripeConfigHandler)
  200. http.HandleFunc("/api/pay/secret", getSecretHandler)
  201. http.HandleFunc("/api/badge", badgeHandler)
  202. http.HandleFunc("/api/healthcheck", healthCheckHandler)
  203. log.Println("Listening on :3000...")
  204. err := http.ListenAndServe(":3000", nil)
  205. if err != nil {
  206. log.Fatal(err)
  207. }
  208. }