Skip to content

Commit

Permalink
Add registration
Browse files Browse the repository at this point in the history
  • Loading branch information
Raeein committed Dec 20, 2022
1 parent 528c8eb commit b8fc34b
Show file tree
Hide file tree
Showing 13 changed files with 414 additions and 113 deletions.
11 changes: 5 additions & 6 deletions .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
name: Push To Docker Hub
on:
push:
branches:
- main
pull_request:
branches:
- main
tags:
- '*'

permissions:
contents: read

Expand All @@ -15,9 +13,10 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Build and Push to Docker Hub
uses: mr-smithers-excellent/docker-build-push@v4
uses: mr-smithers-excellent/docker-build-push@v5
with:
image: ${{ secrets.GMC_DOCKER_REPO }}
tags: v1, latest
registry: docker.io
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
69 changes: 65 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,61 @@
Run the docker image with

# gmc - give me my course

gmc is a full stack app written in go and vanilla javascript that sends you an email when there is a spot available in a course you want to take.
During course selection windows you can find the website running at https://gmc.raeeinbagheri.com

![Screen shot of the landing page](./images/img.png)

# Features

- Sends you an email when there is a spot so you dont have to email greg each semester
- CI/CD pipeline with github actions - deployment to docker hub, google cloud and binaries to github releases
- Firestore for storing contact information and emails
- MongoDB for logging as this is a serverless app

# Run the project

- Download a binary compatible with your machine from the [releases page](https://github.com/Raeein/gmc/releases)

- From Dockerhub
```bash
docker pull raeein/gmc:main-528c8eb
docker run -p 8080:8080 --name gmc --rm \
-e SMTP_HOST=XXXX \
-e SMTP_PORT=XXXX \
-e SMTP_FROM=XXXX \
-e SMTP_PASSWORD=XXXX \
-e MONGO_USERNAME=XXXX \
-e MONGO_PASSWORD=XXXX \
-e MONGO_DATABASE=XXXX \
-e MONGO_COLLECTION=XXXX \
-e FIRESTORE_PROJECTID=XXXX \
-e FIRESTORE_SECTIONS_COLLECTIONID=XXXX \
-e FIRESTORE_USERSCOLLECTIONID=XXXX \
-e FIRESTORE_CREDENTIALSPATH=XXXX \
raeein/gmc:main-528c8eb
/
```
docker run -p 8080:8080 --name delete --rm \

- From source
- You need to have `go` installed on your machine - version 1.19 recommended
- Place your config.yaml in the root of the project
- Have your firestore credential file
- Fll in the config.yaml with your keys and firestore credintial path

```bash
git clone https://github.com/Raeein/gmc.git
cd gmc
go mod download
go run cmd/gmc/main.go
```
OR

- From root of the project

```bash
docoker build -t gmc .
docker run -p 8080:8080 --name gmc --rm \
-e SMTP_HOST=XXXX \
-e SMTP_PORT=XXXX \
-e SMTP_FROM=XXXX \
Expand All @@ -9,6 +64,12 @@ docker run -p 8080:8080 --name delete --rm \
-e MONGO_PASSWORD=XXXX \
-e MONGO_DATABASE=XXXX \
-e MONGO_COLLECTION=XXXX \
test
-e FIRESTORE_PROJECTID=XXXX \
-e FIRESTORE_SECTIONS_COLLECTIONID=XXXX \
-e FIRESTORE_USERSCOLLECTIONID=XXXX \
-e FIRESTORE_CREDENTIALSPATH=XXXX \
gmc
/
```
```

Inspiration: https://github.com/jacobmichels/Course-Sense-Go
54 changes: 40 additions & 14 deletions cmd/gmc/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@ package main
import (
"context"
"github.com/Raeein/gmc/config"
"github.com/Raeein/gmc/email"
"github.com/Raeein/gmc/firestore"
"github.com/Raeein/gmc/mongodb"
"github.com/Raeein/gmc/poll"
"github.com/Raeein/gmc/server"
"github.com/Raeein/gmc/webadvisor"
"log"
"os"
"os/signal"
"time"
)

func main() {
Expand All @@ -17,11 +21,8 @@ func main() {

sig := make(chan os.Signal, 1)
signal.Notify(sig, os.Interrupt)
go func() {
<-sig
log.Println("received interrupt, shutting down")
cancel()
}()

ticker := time.NewTicker(30 * time.Minute)

cfg := config.Read()
mongoService := mongodb.New(
Expand All @@ -34,16 +35,41 @@ func main() {
//mongoService.Log("Info", "test log entry")

webadvisorService := webadvisor.New()
//firestoreService, err := firestore.New(
// ctx,
// cfg.Firestore.ProjectID,
// cfg.Firestore.SectionsCollectionID,
// cfg.Firestore.UsersCollectionID,
// cfg.Firestore.CredentialsPath,
//)
s := server.New(cfg.Server.Port, webadvisorService, mongoService)

firestoreService, err := firestore.New(
ctx,
cfg.Firestore.ProjectID,
cfg.Firestore.SectionsCollectionID,
cfg.Firestore.UsersCollectionID,
cfg.Firestore.CredentialsPath,
)
if err != nil {
log.Fatalf("failed to create firestore service: %v", err)
}
s := server.New(ctx, webadvisorService, firestoreService, mongoService, cfg.Server.Port)
if err != nil {
log.Fatalf("failed to convert port string to int: %v", err)
}
emailService := email.New(cfg.Smtp.Host, cfg.Smtp.Port, cfg.Smtp.From, cfg.Smtp.Password)
trigger := poll.New(webadvisorService, firestoreService, emailService, mongoService)

go func() {
for {
select {
case <-ticker.C:
go trigger.Trigger(ctx)
case <-ctx.Done():
ticker.Stop()
cancel()
case <-sig:
log.Println("received interrupt, shutting down")
ticker.Stop()
cancel()
}
}
}()

s.Start(ctx, cfg.Server.Port)
//fmt.Println("Service is running")
//u := gmc.User{"[email protected]", "Raeein"}
//email.Send(u, []string{"Java", "Python"}, cfg.Smtp.Host, cfg.Smtp.Port, cfg.Smtp.From, cfg.Smtp.Password)
//p := &gmc.User{"[email protected]", "hi"}
Expand Down
46 changes: 32 additions & 14 deletions email/email.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,54 @@ import (
"fmt"
"github.com/Raeein/gmc"
"net/smtp"
"strconv"
"text/template"
)

func Send(u gmc.User, courses []string, host string, port int, from string, passwd string) {
auth := smtp.PlainAuth("", from, passwd, host)
uri := host + ":" + strconv.FormatInt(int64(port), 10)
content, _ := makeContent(u, courses)
err := smtp.SendMail(uri, auth, from, []string{u.Email}, content.Bytes())
if err != nil {
fmt.Println(err)
return
type Service struct {
host string
port string
password string
from string
}

func New(host string, port, password, from string) Service {
return Service{
host: host,
port: port,
password: password,
from: from,
}
}

func (s Service) Send(section gmc.Section, users ...gmc.User) error {
auth := smtp.PlainAuth("", s.from, s.password, s.host)
uri := s.host + ":" + s.port
var err error
for _, u := range users {
content, _ := makeContent(u, section)
e := smtp.SendMail(uri, auth, s.from, []string{u.Email}, content.Bytes())
if e != nil {
fmt.Println(err)
err = e
}
}
fmt.Println("Email Sent!")
return err
}

func makeContent(u gmc.User, courses []string) (bytes.Buffer, error) {
func makeContent(u gmc.User, section gmc.Section) (bytes.Buffer, error) {
var body bytes.Buffer
var tpl *template.Template
mimeHeaders := "MIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\n\n"
body.Write([]byte(fmt.Sprintf("Subject: Spots Availabe \n%s\n\n", mimeHeaders)))

tpl = template.Must(template.ParseGlob("template/*.gohtml"))
tpl = template.Must(template.ParseFiles("email.gohtml"))

_ = tpl.Execute(&body, struct {
Name string
Courses []string
Section gmc.Section
}{
Name: u.Name,
Courses: courses,
Section: section,
})
return body, nil
}
10 changes: 4 additions & 6 deletions template/email.gohtml → email/email.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@
<!DOCTYPE html>
<html>
<body>
<h3>Theres a spot available</h3>
<h3>Theres a spot available to register</h3>
<span>Hey {{.Name}}, These sport are available to register in.</span><br/>
<br/>
<h3>Courses:</h3>
{{range .Courses}}
<tr>
<td>{{ . }}</td>
</tr>
{{ end }}
<p>
{{ .Section.Course.Department }},{{ .Section.Course.Code }}, {{ .Section.Code }}, {{ .Section.Term }}
</p>
<br/>
</body>
</html>
Loading

0 comments on commit b8fc34b

Please sign in to comment.