diff --git a/Dockerfile b/Dockerfile index c65ac9e..c567b61 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,6 @@ RUN go get -u github.com/kardianos/govendor WORKDIR /go/src/app COPY . . -EXPOSE 3000 # Install dependencies RUN govendor sync diff --git a/README.md b/README.md index 408f43a..aa25469 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,52 @@ Web Application that gets students comments on Facebook posts/photos which related to their courses Ahmed Ashraf 37-6150 Omar Ashraf 37-6244 + +Get the vendor tool to declare and isolate the dependencies by writing this command "go get -u github.com/kardianos/govendor" then we use it at the docker file and if you want to use it without docker you can write these two commands "govender sync" and "govendor build". + +We have several enviroment variables which are: + DATABASE_HOST: which is the host database that the app uses + DATABASE_USER: the username of the database + DATABASE_PASSWORD: the password of the database + DATABASE_NAME: the database name + ACCESS_TOKEN: a valid user access token + POSTGRES_PASSWORD: the database password + POSTGRES_USER: the databse username + POSTGRES_DB: the database name + +To Run the Web App using docker run command : + +1.Run the data base with it config (POSTGRES_USER,POSTGRES_PASSWORD,POSTGRES_DB) and give it name "pg_container" +for Example : docker run --name pg_container -e POSTGRES_USER=user -e POSTGRES_PASSWORD=password -e POSTGRES_DB=name -p 5432:5432 -d healthcheck/postgres:alpine +2.Build the App Dockerfile and give it tag guc +for Example : docker build -t guc . + +3.Run the App container with passing the enviroment variables ( DATABASE_HOST DATABASE_USER DATABASE_PASSWORD DATABASE_NAME ACCESS_TOKEN) and set the ports to 3000:8080 +for example : +docker run -e DATABASE_HOST=db -e DATABASE_USER=user -e DATABASE_PASSWORD=password -e DATABASE_NAME=name -e ACCESS_TOKEN=(a valid access token) --link=pg_container:db -p 3000:8080 guc + +--the flags used in the docker run command is : 1.-e to set enviroment variables + 2.-p to set the port of the container + 3.-d Run container in background and print container ID + 4.-t to give your container a tag name + 5.--link to link the host of pg_container to DATABASE_HOST + + +To Run the Web App using docker-compose command : + +1.Set the enviroment variables in the docker-compose.yaml file +for example for: + DATABASE_HOST: db + DATABASE_USER: user + DATABASE_PASSWORD: password + DATABASE_NAME: name + ACCESS_TOKEN: (a valid access token) + POSTGRES_PASSWORD: password + POSTGRES_USER: user + POSTGRES_DB: name +2.Run docker-compose up --build -d , then your app is and built and on +3.to stop the app use docker-compose down and docker-compose stop + +--the flags used in the docker compose command is : + 1.--build to build the container again + 2.-d Run container in background and print container ID diff --git a/docker-compose.yaml b/docker-compose.yaml index 3f677a0..238ffab 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -5,10 +5,10 @@ services: build: . environment: DATABASE_HOST: db - DATABASE_USER: root - DATABASE_PASSWORD: secret - DATABASE_NAME: GUC_Comments - ACCESS_TOKEN: "EAAFDrTDhvyMBAEt2GZAyMW9xPsLNnhz8ZAXh8ehZBTU6b5ug8ciAZBSulKOEDDbS2GtrokaGIKyOZAagiNCvRrZCl1nXaR6xtZBmGoXeSOISqihq7sDM3TZBj6hC2ZCEpwP3In3jo2ZAj5xlPNgMbYTgNWProADC3C2XNWe1FH7egJKwZDZD" + DATABASE_USER: user + DATABASE_PASSWORD: password + DATABASE_NAME: name + ACCESS_TOKEN: (a valid access token) ports: - 3000:8080 depends_on: @@ -18,6 +18,6 @@ services: image: healthcheck/postgres:alpine environment: - POSTGRES_PASSWORD: secret - POSTGRES_USER: root - POSTGRES_DB: GUC_Comments \ No newline at end of file + POSTGRES_PASSWORD: password + POSTGRES_USER: user + POSTGRES_DB: name \ No newline at end of file diff --git a/guc_comments.html b/guc_comments.html new file mode 100644 index 0000000..124b9d9 --- /dev/null +++ b/guc_comments.html @@ -0,0 +1,53 @@ + + + + + + +

GUC Comments

+ +

{{.Course}}

+ + + + + + + + + + {{range .Guccommentss}} + + + + {{end}} +
Comments
+ {{.Comments}} +
+ + \ No newline at end of file diff --git a/main.go b/main.go index e92be23..a6603ae 100644 --- a/main.go +++ b/main.go @@ -6,65 +6,83 @@ import ( "log" - //"os" - //"reflect" + "net/http" + "os" - // fb "github.com/huandu/facebook" + "html/template" + "reflect" + + fb "github.com/huandu/facebook" _ "github.com/lib/pq" ) -// var ( -// dbname = os.Getenv("DATABASE_NAME") -// dbpassword = os.Getenv("DATABASE_PASSWORD") -// dbuser = os.Getenv("DATABASE_USER") -// dbhost = os.Getenv("DATABASE_HOST") -// ac = os.Getenv("ACCESS_TOKEN") -//) - -const ( - dbname = "GUC_Comments" - dbpassword = "secret" - dbuser = "root" - dbhost = "db" +type guccomments struct { + Comments string +} + +type guccommentspageData struct { + Course string + Guccommentss []guccomments +} + +var ( + dbname = os.Getenv("DATABASE_NAME") + dbpassword = os.Getenv("DATABASE_PASSWORD") + dbuser = os.Getenv("DATABASE_USER") + dbhost = os.Getenv("DATABASE_HOST") + ac = os.Getenv("ACCESS_TOKEN") + + db *sql.DB + tpl *template.Template ) +func init() { + var err error + dbInfo := fmt.Sprintf("host=%s user=%s password=%s dbname=%s sslmode=disable", + dbhost, dbuser, dbpassword, dbname) + db, err = sql.Open("postgres", dbInfo) + if err != nil { + panic(err) + } + + if err = db.Ping(); err != nil { + panic(err) + } + fmt.Println("You connected to your database.") + + tpl = template.Must(template.ParseGlob("guc_comments.html")) +} + func main() { - q := ` SELECT table_name FROM information_schema.tables WHERE table_schema='public' AND table_type='BASE TABLE'` + q := ` SELECT table_name + FROM information_schema.tables + WHERE table_schema='public' AND table_type='BASE TABLE'` + q1 := `SELECT CourseId,CourseName + FROM Courses ` + qcreate := `CREATE TABLE Courses ( CourseId SERIAL PRIMARY KEY, - CourseName VARCHAR(30) - + CourseName TEXT ); - CREATE TABLE Comments ( CourseId INTEGER REFERENCES Courses(CourseId), - Comment VARCHAR(50) - + Comment TEXT );` - dbInfo := fmt.Sprintf("host=%s user=%s password=%s dbname=%s sslmode=disable", - dbhost, dbuser, dbpassword, dbname) + qinsertCourses := `INSERT INTO Courses(CourseId ,CourseName ) VALUES + (DEFAULT,'CSEN 702 Microprocessors'), + (DEFAULT,'CSEN 703 Analysis and Design of Algorithms'), + (DEFAULT,'CSEN 704 Advanced computer lab');` - db, err := sql.Open("postgres", - dbInfo) - if err != nil { - log.Fatal("Error: The data source arguments are not valid") - } + db.Exec(qcreate) - err = db.Ping() + Result, err := db.Exec(qinsertCourses) if err != nil { log.Fatal(err) } - log.Print("connected") - - Result, err := db.Exec(qcreate) - if (err) != nil { - log.Fatal(err) - } - - log.Print(Result) + fmt.Println(Result) rows, err := db.Query(q) if (err) != nil { @@ -79,77 +97,219 @@ func main() { } log.Printf("Table name is %s", tableName) } - log.Printf("hey again") + rows2, err := db.Query(q1) + + for rows2.Next() { + var ( + courseName string + courseid int + ) + if err := rows2.Scan(&courseid, &courseName); err != nil { + log.Fatal(err) + } + log.Printf("course name is %s and id is %d", courseName, courseid) + } + + res, err := fb.Get("582313518881669_582751342171220/comments", fb.Params{ + "fields": "message", + "access_token": ac, + }) + + if (err) != nil { + log.Fatal(err) + + } + + s, _ := res["data"].([]interface{}) + + for i := 0; i < reflect.ValueOf(s).Len(); i++ { + + msg := s[i].(map[string]interface{}) + + qinsertcomment := fmt.Sprintf(`INSERT INTO Comments(CourseId, Comment) VALUES (1 ,'%s')`, + msg["message"]) + + Result, err := db.Exec(qinsertcomment) + if err != nil { + log.Fatal(err) + } + fmt.Println(Result) + fmt.Println(qinsertcomment) + } + + fmt.Println("") + + res2, _ := fb.Get("582313518881669_582750698837951/comments", fb.Params{ + "fields": "message", + "access_token": ac}) + + r, _ := res2["data"].([]interface{}) + + for i := 0; i < reflect.ValueOf(r).Len(); i++ { + + msg := r[i].(map[string]interface{}) + + qinsertcomment := fmt.Sprintf(`INSERT INTO Comments(CourseId, Comment) VALUES (2 ,'%s')`, + msg["message"]) + + Result, err := db.Exec(qinsertcomment) + if err != nil { + log.Fatal(err) + } + fmt.Println(Result) + fmt.Println(qinsertcomment) + } - // res, err := fb.Get("582313518881669_582751342171220/comments", fb.Params{ - // "fields": "message", - // "access_token": ac, - // }) + fmt.Println("") - // if (err) != nil { - // log.Fatal(err) + res3, _ := fb.Get("582313518881669_582751015504586/comments", fb.Params{ + "fields": "message", + "access_token": ac}) - // } - // s, _ := res["data"].([]interface{}) + v, _ := res3["data"].([]interface{}) - // for i := 0; i < reflect.ValueOf(s).Len(); i++ { + for i := 0; i < reflect.ValueOf(v).Len(); i++ { - // msg := s[i].(map[string]interface{}) + msg := v[i].(map[string]interface{}) - // fmt.Println(msg["message"]) - // } + qinsertcomment := fmt.Sprintf(`INSERT INTO Comments(CourseId, Comment) VALUES (3 ,'%s')`, + msg["message"]) - // fmt.Println("") + Result, err := db.Exec(qinsertcomment) + if err != nil { + log.Fatal(err) + } + fmt.Println(Result) + fmt.Println(qinsertcomment) + } - // res2, _ := fb.Get("582313518881669_582750698837951/comments", fb.Params{ - // "fields": "message", - // "access_token": ac}) + q222 := `SELECT Comment + FROM Comments + INNER JOIN Courses ON Courses.CourseId = Comments.CourseId + WHERE Courses.CourseName = 'CSEN 702 Microprocessors' ` - // r, _ := res2["data"].([]interface{}) + rows5555, err := db.Query(q222) - // for i := 0; i < reflect.ValueOf(r).Len(); i++ { + if (err) != nil { + log.Fatal(err) + } + defer rows5555.Close() + gucs := make([]guccomments, 0) + for rows5555.Next() { + guc := guccomments{} + if err := rows5555.Scan(&guc.Comments); err != nil { + log.Fatal(err) + } + fmt.Println(guc.Comments) + gucs = append(gucs, guc) - // msg := r[i].(map[string]interface{}) + } + http.HandleFunc("/", defaultHandler) + http.HandleFunc("/MICRO", microHandler) + http.HandleFunc("/ANALYSIS", analysisHandler) + http.HandleFunc("/ADVANCED", advancedHandler) + http.ListenAndServe(":8080", nil) - // fmt.Println(msg["message"]) - // } +} - // res3, _ := fb.Get("582313518881669_582751015504586/comments", fb.Params{ - // "fields": "message", - // "access_token": ac}) +func defaultHandler(w http.ResponseWriter, r *http.Request) { - // v, _ := res3["data"].([]interface{}) + p := make([]guccomments, 0) + data := guccommentspageData{ + Course: " ", + Guccommentss: p, + } + t, _ := template.ParseFiles("guc_comments.html") + t.Execute(w, data) +} - // for i := 0; i < reflect.ValueOf(v).Len(); i++ { +func microHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + http.Error(w, http.StatusText(405), http.StatusMethodNotAllowed) + } + q := `SELECT Comment + FROM Comments + INNER JOIN Courses ON Courses.CourseId = Comments.CourseId + WHERE Courses.CourseName = 'CSEN 702 Microprocessors' ` - // msg := v[i].(map[string]interface{}) + rows5555, err := db.Query(q) - // fmt.Println(msg["message"]) - // } - /* http.HandleFunc("/", defaultHandler) // default directory - http.HandleFunc("/MICRO", microHandler) - http.HandleFunc("/ANALYSIS", analysisHandler) - http.HandleFunc("/ANDVANCED", advancedHandler) - http.ListenAndServe(":3000", nil)*/ + if (err) != nil { + log.Fatal(err) + } + defer rows5555.Close() + gucs := make([]guccomments, 0) + for rows5555.Next() { + guc := guccomments{} + if err := rows5555.Scan(&guc.Comments); err != nil { + log.Fatal(err) + } + fmt.Println(guc.Comments) + gucs = append(gucs, guc) + + } - // fmt.Print("hiii sobky") - // http.HandleFunc("/", defaultHandler) // default directory - // http.HandleFunc("/MICRO", microHandler) - // http.HandleFunc("/ANALYSIS", analysisHandler) - // http.HandleFunc("/ANDVANCED", advancedHandler) - // http.ListenAndServe(":3000", nil) + data := guccommentspageData{ + Course: "CSEN 702 Microprocessors", + Guccommentss: gucs, + } + t, _ := template.ParseFiles("guc_comments.html") + t.Execute(w, data) } +func analysisHandler(w http.ResponseWriter, r *http.Request) { + q := `SELECT Comment + FROM Comments + INNER JOIN Courses ON Courses.CourseId = Comments.CourseId + WHERE Courses.CourseName = 'CSEN 703 Analysis and Design of Algorithms' ` + rows, err := db.Query(q) -// func defaultHandler(w http.ResponseWriter, r *http.Request) { -// fmt.Fprintln(w, "Hello, Web!") -// } -// func microHandler(w http.ResponseWriter, r *http.Request) { -// fmt.Fprintln(w, "Hello, micro!") -// } -// func analysisHandler(w http.ResponseWriter, r *http.Request) { -// fmt.Fprintln(w, "Hello, analysis!") -// } -// func advancedHandler(w http.ResponseWriter, r *http.Request) { -// fmt.Fprintln(w, "Hello, advanced!") -// } + if (err) != nil { + log.Fatal(err) + } + gucs := make([]guccomments, 0) + for rows.Next() { + guc := guccomments{} + if err := rows.Scan(&guc.Comments); err != nil { + log.Fatal(err) + } + + gucs = append(gucs, guc) + + } + data := guccommentspageData{ + Course: "CSEN 703 Analysis and Design of Algorithms", + Guccommentss: gucs, + } + + t, _ := template.ParseFiles("guc_comments.html") + t.Execute(w, data) +} +func advancedHandler(w http.ResponseWriter, r *http.Request) { + q := `SELECT Comment + FROM Comments + INNER JOIN Courses ON Courses.CourseId = Comments.CourseId + WHERE Courses.CourseName = 'CSEN 704 Advanced computer lab' ` + rows, err := db.Query(q) + + if (err) != nil { + log.Fatal(err) + } + gucs := make([]guccomments, 0) + for rows.Next() { + guc := guccomments{} + if err := rows.Scan(&guc.Comments); err != nil { + log.Fatal(err) + } + + gucs = append(gucs, guc) + + } + data := guccommentspageData{ + Course: "CSEN 704 Advanced computer lab", + Guccommentss: gucs, + } + + t, _ := template.ParseFiles("guc_comments.html") + t.Execute(w, data) +}