Skip to content

Commit

Permalink
added async version of summary-fn summary page
Browse files Browse the repository at this point in the history
  • Loading branch information
maximilien committed Nov 15, 2019
1 parent 5f84795 commit 06a4918
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 40 deletions.
67 changes: 67 additions & 0 deletions funcs/summary/async_layout.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<head>
<h1>{{.PageTitle}}</h1>
<meta charset="utf-8">

<link rel="stylesheet" href="http://mistic100.github.io/jQCloud/dist/jqcloud2/dist/jqcloud.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="http://mistic100.github.io/jQCloud/dist/jqcloud2/dist/jqcloud.min.js"></script>

<style>
#cloud {
width: 700px;
height: 300px;
}
</style>
<script type="text/javascript">
$(document).ready(function() {
$('.content-link').click(function(e) {
e.preventDefault();

$('html, body').animate({
scrollTop: $('#profile-body').offset().top
}, 500);
});
});
</script>
</head>
<body>
<div id="cloud"></div>
<script type="text/javascript">
var words = [];
</script>
<div>
{{$WatsonFnURL := .WatsonFnURL}}
{{$Timeout := .Timeout}}
{{range $i, $tweet := .Tweets}}
<div>
{{range $j, $imageURL := $tweet.ImageURLs}}
<div id="#{{$i}}_{{$j}}">
<img src="{{$imageURL}}">
</div>
<div>
{{$ClassifiedImage := (ClassifyImage $WatsonFnURL $imageURL $Timeout)}}
{{range $ClassifiedImage.Classifiers}}
<div>
{{range .Classes}}
<div>{{.Name}} ({{.Score}})
<script type="text/javascript">
words.push({text:"{{.Name}}",
weight:{{.Score}}*1000,
link:"#{{$i}}_{{$j}}"})
</script>
</div>
{{end}}
</div>
{{end}}
</div>
{{end}}
<div>{{.Text}}</div>
<br/>
<hr/>
</div>
{{end}}
</div>
<script type="text/javascript">
$('#cloud').jQCloud(words);
</script>
</body>
2 changes: 2 additions & 0 deletions funcs/summary/cmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ func Execute() error {
func (summaryFn *SummaryFn) summary(cmd *cobra.Command, args []string) error {
if summaryFn.StartServer {
http.HandleFunc("/", summaryFn.SummaryHandler)
http.HandleFunc("/async", summaryFn.SummaryAsyncHandler)

return http.ListenAndServe(fmt.Sprintf(":%d", summaryFn.Port), nil)
} else {
classifiedTweets, err := summaryFn.Summary()
Expand Down
4 changes: 2 additions & 2 deletions funcs/summary/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ <h1>{{.PageTitle}}</h1>
var words = [];
</script>
<div>
{{range $i, $tweet := .Tweets}}
{{range $i, $cTweet := .ClassifiedTweets}}
<div>
{{range $j, $ClassifiedImage := $tweet.ClassifiedImages}}
{{range $j, $ClassifiedImage := $cTweet.ClassifiedImages}}
<div id="#{{$i}}_{{$j}}">
<img src="{{$ClassifiedImage.ResolvedURL}}">
</div>
Expand Down
123 changes: 85 additions & 38 deletions funcs/summary/summary.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"io/ioutil"
"log"
"net/http"
"path"
"time"

"github.com/maximilien/knfun/funcs/common"
Expand Down Expand Up @@ -66,7 +67,12 @@ type SummaryFn struct {

type SummaryPageData struct {
PageTitle string
Tweets []ClassifiedTweet

Tweets []Tweet
ClassifiedTweets []ClassifiedTweet

WatsonFnURL string
Timeout int
}

func (summaryFn *SummaryFn) Summary() ([]ClassifiedTweet, error) {
Expand All @@ -85,8 +91,8 @@ func (summaryFn *SummaryFn) SummaryHandler(writer http.ResponseWriter, request *

tmpl := template.Must(template.ParseFiles("./funcs/summary/layout.html"))
data := SummaryPageData{
PageTitle: fmt.Sprintf("Recent tweets with images for search `%s`", summaryFn.SearchString),
Tweets: classifiedTweets,
PageTitle: fmt.Sprintf("Recent tweets with images for search `%s`", summaryFn.SearchString),
ClassifiedTweets: classifiedTweets,
}

err = tmpl.Execute(writer, data)
Expand All @@ -96,74 +102,79 @@ func (summaryFn *SummaryFn) SummaryHandler(writer http.ResponseWriter, request *
}
}

// Private SummaryFn

func (summaryFn *SummaryFn) searchTweets(searchString string, count int) ([]Tweet, error) {
var err error

twitterFnClient := http.Client{
Timeout: time.Second * time.Duration(summaryFn.Timeout),
}
func (summaryFn *SummaryFn) SummaryAsyncHandler(writer http.ResponseWriter, request *http.Request) {
summaryFn.InitCommonQueryParams(request)
log.Printf("SummaryFn.Summary: s=\"%s\", c=\"%d\", o=\"%s\"", summaryFn.SearchString, summaryFn.Count, summaryFn.Output)

url := fmt.Sprintf("%s?q=%s&c=%d&o=json", summaryFn.TwitterFnURL, searchString, count)
req, err := http.NewRequest(http.MethodGet, url, nil)
tweets, err := summaryFn.searchTweets(summaryFn.SearchString, summaryFn.Count)
if err != nil {
return []Tweet{}, err
log.Printf("Error collecting tweets: %s\n", err.Error())
return
}

req.Header.Set("User-Agent", "application/json")
tmplName := path.Base("./funcs/summary/async_layout.html")
tmpl := template.New(tmplName)
tmpl.Funcs(template.FuncMap{
"ClassifyImage": func(watsonFnURL string, imageURL string, timeout int) (ClassifiedImage, error) {
return classifyImage(watsonFnURL, imageURL, timeout)
},
})

res, err := twitterFnClient.Do(req)
tmpl, err = tmpl.ParseFiles("./funcs/summary/async_layout.html")
if err != nil {
return []Tweet{}, err
log.Printf("Error parsing Golang template for tweets: %s\n", err.Error())
return
}

body, err := ioutil.ReadAll(res.Body)
if err != nil {
return []Tweet{}, err
data := SummaryPageData{
PageTitle: fmt.Sprintf("Recent tweets for search `%s`", summaryFn.SearchString),
Tweets: tweets,

WatsonFnURL: summaryFn.WatsonFnURL,
Timeout: summaryFn.Timeout,
}

tweets := []Tweet{}
err = json.Unmarshal(body, &tweets)
err = tmpl.Execute(writer, data)
if err != nil {
return []Tweet{}, err
log.Printf("Error executing template with tweets: %s\n", err.Error())
return
}

return tweets, nil
}

func (summaryFn *SummaryFn) classifyImage(imageURL string) (ClassifiedImage, error) {
// Private SummaryFn

func (summaryFn *SummaryFn) searchTweets(searchString string, count int) ([]Tweet, error) {
var err error

watsonFnClient := http.Client{
twitterFnClient := http.Client{
Timeout: time.Second * time.Duration(summaryFn.Timeout),
}

url := fmt.Sprintf("%s?q=%s&o=json", summaryFn.WatsonFnURL, imageURL)
url := fmt.Sprintf("%s?q=%s&c=%d&o=json", summaryFn.TwitterFnURL, searchString, count)
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return ClassifiedImage{}, err
return []Tweet{}, err
}

req.Header.Set("User-Agent", "application/json")

res, err := watsonFnClient.Do(req)
res, err := twitterFnClient.Do(req)
if err != nil {
return ClassifiedImage{}, err
return []Tweet{}, err
}

body, err := ioutil.ReadAll(res.Body)
if err != nil {
return ClassifiedImage{}, err
return []Tweet{}, err
}

classifiedImage := ClassifiedImage{}
err = json.Unmarshal(body, &classifiedImage)
tweets := []Tweet{}
err = json.Unmarshal(body, &tweets)
if err != nil {
return ClassifiedImage{}, err
return []Tweet{}, err
}

return classifiedImage, nil
return tweets, nil
}

func (summaryFn *SummaryFn) collectTweetsWithImages(tweets []Tweet) []Tweet {
Expand All @@ -187,7 +198,7 @@ func (summaryFn *SummaryFn) collectClassifiedTweets() ([]ClassifiedTweet, error)
for _, tweet := range tweetsWithImages {
classifiedImages := []ClassifiedImage{}
for _, imageURL := range tweet.ImageURLs {
classifiedImage, err := summaryFn.classifyImage(imageURL)
classifiedImage, err := classifyImage(summaryFn.WatsonFnURL, imageURL, summaryFn.Timeout)
if err != nil {
return []ClassifiedTweet{}, err
}
Expand All @@ -202,7 +213,43 @@ func (summaryFn *SummaryFn) collectClassifiedTweets() ([]ClassifiedTweet, error)
return classifiedTweets, nil
}

// Private ClassifiedTweet
// Private function

func classifyImage(watsonFnURL string, imageURL string, timeout int) (ClassifiedImage, error) {
var err error

watsonFnClient := http.Client{
Timeout: time.Second * time.Duration(timeout),
}

url := fmt.Sprintf("%s?q=%s&o=json", watsonFnURL, imageURL)
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return ClassifiedImage{}, err
}

req.Header.Set("User-Agent", "application/json")

res, err := watsonFnClient.Do(req)
if err != nil {
return ClassifiedImage{}, err
}

body, err := ioutil.ReadAll(res.Body)
if err != nil {
return ClassifiedImage{}, err
}

classifiedImage := ClassifiedImage{}
err = json.Unmarshal(body, &classifiedImage)
if err != nil {
return ClassifiedImage{}, err
}

return classifiedImage, nil
}

// ClassifiedTweet

func (cTweet ClassifiedTweet) ToText() string {
sb := bytes.NewBufferString("")
Expand Down

0 comments on commit 06a4918

Please sign in to comment.