2019-04-13 12:31:28 +02:00
package main
import (
2019-04-13 15:25:50 +02:00
"bytes"
2019-04-13 12:31:28 +02:00
"encoding/json"
"io/ioutil"
"net/http"
2019-04-13 15:25:50 +02:00
"strconv"
2019-04-19 21:35:01 +02:00
"strings"
2019-04-13 19:19:24 +02:00
2019-04-22 16:30:52 +02:00
log "github.com/sirupsen/logrus"
2019-04-19 21:35:01 +02:00
"text/template"
// "github.com/davecgh/go-spew/spew"
2019-04-13 15:25:50 +02:00
// "os"
2019-04-13 12:31:28 +02:00
)
func setupListener ( ) {
httpURI := cfg . Section ( "http" ) . Key ( "http_uri" ) . String ( )
httpPort := cfg . Section ( "http" ) . Key ( "http_port" ) . String ( )
mux := http . NewServeMux ( )
mux . HandleFunc ( httpURI , PostHandler )
2019-04-20 14:59:08 +02:00
log . Debugf ( "listening on port %s" , httpPort )
2019-04-13 12:31:28 +02:00
log . Fatal ( http . ListenAndServe ( ":" + httpPort , mux ) )
}
// PostHandler converts post request body to string
func PostHandler ( w http . ResponseWriter , r * http . Request ) {
2019-04-19 21:35:01 +02:00
2019-04-13 12:31:28 +02:00
if r . Method == "POST" {
body , err := ioutil . ReadAll ( r . Body )
if err != nil {
http . Error ( w , "Error reading request body" ,
http . StatusInternalServerError )
}
2019-04-22 16:30:52 +02:00
// Unmarshall data and get room to post to
2019-04-13 12:31:28 +02:00
var postData GiteaPostData
json . Unmarshal ( body , & postData )
2019-04-19 21:35:01 +02:00
args := strings . Split ( r . URL . String ( ) , "/" )
room := args [ len ( args ) - 1 ]
2019-04-22 16:30:52 +02:00
// Check token
2019-04-19 21:35:01 +02:00
if mygiteabot . checkToken ( room , postData . Secret ) {
2019-04-22 16:30:52 +02:00
log . Debugf ( "Posting to room: %s" , room )
msgType := cfg . Section ( "bot" ) . Key ( "message_type" ) . String ( )
//TODO check for configured message type
2019-04-22 20:34:05 +02:00
messageText , err := generateTextMessage ( postData , r . Header . Get ( "X-Gitea-Event" ) )
if err != nil {
log . Warning ( err )
log . Warning ( postData )
}
2019-04-22 16:30:52 +02:00
switch msgType {
case "html" :
2019-04-22 20:34:05 +02:00
messageHTML , err := generateHTMLMessage ( postData , r . Header . Get ( "X-Gitea-Event" ) )
if err != nil {
log . Warning ( err )
log . Warning ( postData )
}
2019-04-22 16:30:52 +02:00
mygiteabot . SendHTMLToRoom ( room , messageHTML , messageText )
case "plain" :
mygiteabot . SendTextToRoom ( room , messageText )
default :
log . Fatalf ( "Wrong message type %s. Supported 'html' and 'plain'" , msgType )
}
2019-04-19 21:35:01 +02:00
} else {
2019-04-20 14:59:08 +02:00
log . Warningf ( "Wrong token %s for room: %s" , postData . Secret , room )
2019-04-19 21:35:01 +02:00
}
2019-04-14 20:43:16 +02:00
2019-04-13 12:31:28 +02:00
} else {
http . Error ( w , "Invalid request method" , http . StatusMethodNotAllowed )
}
}
2019-04-22 16:30:52 +02:00
//generateTextMessage generates the message string for a given event
2019-04-22 20:34:05 +02:00
func generateHTMLMessage ( data GiteaPostData , eventHeader string ) ( string , error ) {
2019-04-22 16:30:52 +02:00
templHeader := ` <h3><a href=" {{ .Repository .HTMLURL }} "><b><span data-mx-color="#000000">[ {{ .Repository .FullName }} ]</span></b></a></h3> `
mxc , err := mygiteabot . Client . UploadLink ( data . Sender . AvatarURL )
if err != nil {
log . Error ( "Cound not upload user avatar" )
log . Error ( err )
templHeader = templHeader + ` <img src='mxc://matrix.org/GZtGmjBmfljRasPdjvWdKKVe' alt='[gitea]' width='32' height='32' title='gitea'/> <span data-mx-color="#609926"> {{ .Sender .FullName }} </span> `
} else {
templHeader = templHeader + "<img src='" + mxc . ContentURI + ` ' alt='[gitea]' width='30' height='30' title='image title'/> <span data-mx-color="#609926"> {{ .Sender .FullName }} </span> `
}
2019-04-13 15:25:50 +02:00
templ := template . New ( "notification" )
var tpl bytes . Buffer
2019-04-22 16:30:52 +02:00
mesgTemplates := map [ string ] string {
"push" : "pushed " + strconv . Itoa ( len ( data . Commits ) ) + " commit(s) to {{.Repository.Name}}" ,
2019-04-23 17:57:32 +02:00
"issues.assigned" : "assigned issue <b>#{{.Issue.Number}}</b> <i>{{.Issue.Title}}</i> to {{}}" ,
"issues.closed" : "closed issue <b>#{{.Issue.Number}}</b> <i>{{.Issue.Title}}</i>" ,
"issues.demilestoned" : "removed milestone TODO from issue <b>#{{.Issue.Number}}</b> <i>{{.Issue.Title}}</i>" ,
"issues.edited" : "edited issue <b>#{{.Issue.Number}}</b> <i>{{.Issue.Title}}</i>" ,
"issues.label_cleared" : "cleared labels from issue <b>#{{.Issue.Number}}</b> <i>{{.Issue.Title}}</i>" ,
"issues.label_updated" : "updated labels of issue <b>#{{.Issue.Number}}</b> <i>{{.Issue.Title}}</i>" ,
"issues.milestoned" : "added issue <b>#{{.Issue.Number}}</b> <i>{{.Issue.Title}}</i> to milestone TODO" ,
"issues.opened" : "opened issue <b>#{{.Issue.Number}}</b> <i>{{.Issue.Title}}</i>" ,
"issues.reopened" : "re-opened issue <b>#{{.Issue.Number}}</b> <i>{{.Issue.Title}}</i>" ,
"issues.synchronized" : "synchronized issue <b>#{{.Issue.Number}}</b> <i>{{.Issue.Title}}</i>" ,
"issues.unassigned" : "removed assignee from issue <b>#{{.Issue.Number}}</b> <i>{{.Issue.Title}}</i>" ,
2019-04-22 16:30:52 +02:00
"fork" : "forked repository {{.Repository.Parent.FullName}} to {{.Repository.FullName}}" ,
2019-04-23 17:57:32 +02:00
"pull_request.assigned" : "assigned pull-request <b>#.PullRequest.Number}}</b> <i>#{{PullRequest.Title}}</i> to {{.PullRequest.Assignee.FullName}}" ,
"pull_request.closed" : "closed pull-request <b>#.PullRequest.Number}}</b> <i>#{{PullRequest.Title}}</i>" ,
"pull_request.demilestoned" : "removed milestone TODO from pull-request <b>#.PullRequest.Number}}</b> <i>#{{PullRequest.Title}}</i>" ,
"pull_request.edited" : "edited pull-request <b>#.PullRequest.Number}}</b> <i>#{{PullRequest.Title}}</i>" ,
"pull_request.label_cleared" : "removed labels from pull-request <b>#.PullRequest.Number}}</b> <i>#{{PullRequest.Title}}</i>" ,
"pull_request.label_updated" : "updated labels from pull-request <b>#.PullRequest.Number}}</b> <i>#{{PullRequest.Title}}</i>" ,
"pull_request.milestoned" : "added pull-request <b>#.PullRequest.Number}}</b> <i>#{{PullRequest.Title}}</i> to milestone TODO" ,
"pull_request.opened" : "opened pull-request <b>#.PullRequest.Number}}</b> <i>#{{PullRequest.Title}}</i>" ,
"pull_request.reopened" : "re-opened pull-request <b>#.PullRequest.Number}}</b> <i>#{{PullRequest.Title}}</i>" ,
"pull_request.synchronized" : "synchronized pull-request <b>#.PullRequest.Number}}</b> <i>#{{PullRequest.Title}}</i>" ,
"pull_request.unassigned" : "removed assinee from pull-request <b>#.PullRequest.Number}}</b> <i>#{{PullRequest.Title}}</i>" ,
2019-04-22 16:30:52 +02:00
"issue_comment.created" : "commented on issue <b>#{{.Issue.Number}}</b> <i>{{.Issue.Title}}</i>:<br> <pre><code class='language-markdown'>{{.Comment.Body}}</code></pre>" ,
2019-04-23 17:57:32 +02:00
"issue_comment.deleted" : "deleted commented on <b>#{{.Issue.Number}}</b> <i>{{.Issue.Title}}</i>" ,
2019-04-22 16:30:52 +02:00
"repository.created" : "created repository {{}}" ,
"repository.deleted" : "deleted repository {{}}" ,
"release.published" : "published release {{}}" ,
"release.updated" : "updated release {{}}" ,
"release.deleted" : "deleted release {{}}" ,
2019-04-23 17:57:32 +02:00
"pull_request_aproved" : "approved pull request <b>#.PullRequest.Number}}</b> <i>#{{PullRequest.Title}}</i>" ,
"pull_request_rejected" : "rejected pull request <b>#.PullRequest.Number}}</b> <i>#{{PullRequest.Title}}</i>" ,
"pull_request_comment" : "commented on pull request <b>#.PullRequest.Number}}</b> <i>#{{PullRequest.Title}}</i>: <pre><code class='language-markdown'>{{.Comment.Body}}</code><pre>" ,
2019-04-22 16:30:52 +02:00
}
2019-04-13 15:25:50 +02:00
2019-04-22 16:30:52 +02:00
switch eventHeader {
2019-04-13 15:25:50 +02:00
case "push" :
2019-04-22 16:30:52 +02:00
templ . Parse ( templHeader + mesgTemplates [ "push" ] )
2019-04-13 15:25:50 +02:00
case "issues" :
2019-04-22 16:30:52 +02:00
templ . Parse ( templHeader + mesgTemplates [ "issues." + data . Action ] )
2019-04-13 15:25:50 +02:00
case "fork" :
2019-04-22 16:30:52 +02:00
templ . Parse ( templHeader + mesgTemplates [ "fork" ] )
2019-04-13 15:25:50 +02:00
case "pull_request" :
2019-04-22 16:30:52 +02:00
templ . Parse ( templHeader + mesgTemplates [ "pull_request." + data . Action ] )
2019-04-13 15:25:50 +02:00
case "issue_comment" :
2019-04-22 16:30:52 +02:00
templ . Parse ( templHeader + mesgTemplates [ "issue_comment." + data . Action ] )
2019-04-13 15:25:50 +02:00
case "repository" :
2019-04-22 16:30:52 +02:00
templ . Parse ( templHeader + mesgTemplates [ "repository." + data . Action ] )
2019-04-13 15:25:50 +02:00
case "release" :
2019-04-22 16:30:52 +02:00
templ . Parse ( templHeader + mesgTemplates [ "release." + data . Action ] )
2019-04-13 15:25:50 +02:00
case "pull_request_approved" :
2019-04-22 16:30:52 +02:00
templ . Parse ( templHeader + mesgTemplates [ "pull_request_aproved" ] )
2019-04-13 15:25:50 +02:00
case "pull_request_rejected" :
2019-04-22 16:30:52 +02:00
templ . Parse ( templHeader + mesgTemplates [ "pull_request_rejected" ] )
2019-04-13 15:25:50 +02:00
case "pull_request_comment" :
2019-04-22 16:30:52 +02:00
templ . Parse ( templHeader + mesgTemplates [ "pull_request_comment" ] )
default :
log . Warningf ( "Unknown action: %s for eventHeader %s" , data . Action , eventHeader )
templ . Parse ( "Gitea did something unexpected, seriously wtf was that?! Event: " + eventHeader + " Action: " + data . Action )
}
2019-04-13 19:19:24 +02:00
2019-04-22 16:30:52 +02:00
if err := templ . Execute ( & tpl , data ) ; err != nil {
2019-04-22 20:34:05 +02:00
log . Warningf ( "Failed to generate text-message for eventHeader %v" , eventHeader )
return "" , err
2019-04-22 16:30:52 +02:00
}
2019-04-22 20:34:05 +02:00
return tpl . String ( ) , nil
2019-04-22 16:30:52 +02:00
}
//generateTextMessage generates the message string for a given event
2019-04-22 20:34:05 +02:00
func generateTextMessage ( data GiteaPostData , eventHeader string ) ( string , error ) {
2019-04-22 16:30:52 +02:00
templ := template . New ( "notification" )
var tpl bytes . Buffer
mesgTemplates := map [ string ] string {
"push" : "[{{.Repository.Fullname}}] {{.Pusher.FullName}} pushed " + strconv . Itoa ( len ( data . Commits ) ) + " commit(s) to {{.Repository.Name}}" ,
"issues.assigned" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} assigned issue #{{.Issue.Number}} {{.Issue.Title}} to {{}}" ,
"issues.closed" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} closed issue #{{.Issue.Number}} {{.Issue.Title}}" ,
"issues.demilestoned" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} removed milestone TODO from issue #{{.Issue.Number}} {{.Issue.Title}}" ,
"issues.edited" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} edited issue #{{.Issue.Number}} {{.Issue.Title}}" ,
"issues.label_cleared" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} cleared labels from issue #{{.Issue.Number}} {{.Issue.Title}}" ,
"issues.label_updated" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} updated labels of issue #{{.Issue.Number}} {{.Issue.Title}}" ,
"issues.milestoned" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} added issue #{{.Issue.Number}} {{.Issue.Title}} to milestone TODO" ,
"issues.opened" : "[{{.Repository.FullName}}]: {{.Issue.User.FullName}} opened issue #{{.Issue.Number}} {{.Issue.Title}}" ,
"issues.reopened" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} re-opened issue #{{.Issue.Number}} {{.Issue.Title}}" ,
"issues.synchronized" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} synchronized issue #{{.Issue.Number}} {{.Issue.Title}}" ,
"issues.unassigned" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} removed assignee from issue #{{.Issue.Number}} {{.Issue.Title}}" ,
"fork" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} forked repository {{.Repository.Parent.FullName}} to {{.Repository.FullName}}" ,
"pull_request.assigned" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} assigned pull-request #{{.PullRequest.Number}} \"{{.PullRequest.Title}}\" to {{.PullRequest.Assignee.FullName}}" ,
"pull_request.closed" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} closed pull-request #{{.PullRequest.Number}} \"{{.PullRequest.Title}}\"" ,
"pull_request.demilestoned" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} removed milestone TODO from pull-request #{{.PullRequest.Number}} \"{{.PullRequest.Title}}\"" ,
"pull_request.edited" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} edited pull-request #{{.PullRequest.Number}} \"{{.PullRequest.Title}}\"" ,
"pull_request.label_cleared" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} removed labels from pull-request #{{.PullRequest.Number}} \"{{.PullRequest.Title}}\"" ,
"pull_request.label_updated" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} updated labels from pull-request #{{.PullRequest.Number}} \"{{.PullRequest.Title}}\"" ,
"pull_request.milestoned" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} added pull-request #{{.PullRequest.Number}} \"{{.PullRequest.Title}}\" to milestone TODO" ,
"pull_request.opened" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} opened pull-request #{{.PullRequest.Number}} \"{{.PullRequest.Title}}\"" ,
"pull_request.reopened" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} re-opened pull-request #{{.PullRequest.Number}} \"{{.PullRequest.Title}}\"" ,
"pull_request.synchronized" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} synchronized pull-request #{{.PullRequest.Number}} \"{{.PullRequest.Title}}\"" ,
"pull_request.unassigned" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} removed assinee from pull-request #{{.PullRequest.Number}} \"{{.PullRequest.Title}}\"" ,
"issue_comment.created" : "{{.Sender.FullName}} commented on #{{.Issue.Number}} {{.Issue.Title}}: {{.Comment.Body}}" ,
"issue_comment.deleted" : "{{.Sender.FullName}} deleted commented on #{{.Issue.Number}} {{.Issue.Title}}" ,
"repository.created" : "{{.Sender.FullName}} created repository {{}}" ,
"repository.deleted" : "{{.Sender.FullName}} deleted repository {{}}" ,
"release.published" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} published release {{}}" ,
"release.updated" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} updated release {{}}" ,
"release.deleted" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} deleted release {{}}" ,
"pull_request_aproved" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} approved pull request #{{.PullRequest.Number}} \"{{.PullRequest.Title}}\"" ,
"pull_request_rejected" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} rejected pull request #{{.PullRequest.Number}} \"{{.PullRequest.Title}}\"" ,
"pull_request_comment" : "[{{.Repository.FullName}}]: {{.Sender.FullName}} commented on pull request #{{.PullRequest.Number}} \"{{.PullRequest.Title}}\": {{.Comment.Body}}" ,
}
switch eventHeader {
case "push" :
templ . Parse ( mesgTemplates [ "push" ] )
case "issues" :
templ . Parse ( mesgTemplates [ "issues." + data . Action ] )
case "fork" :
templ . Parse ( mesgTemplates [ "fork" ] )
case "pull_request" :
templ . Parse ( mesgTemplates [ "pull_request." + data . Action ] )
case "issue_comment" :
templ . Parse ( mesgTemplates [ "issue_comment." + data . Action ] )
case "repository" :
templ . Parse ( mesgTemplates [ "repository." + data . Action ] )
case "release" :
templ . Parse ( mesgTemplates [ "release." + data . Action ] )
case "pull_request_approved" :
templ . Parse ( mesgTemplates [ "pull_request_aproved" ] )
case "pull_request_rejected" :
templ . Parse ( mesgTemplates [ "pull_request_rejected" ] )
case "pull_request_comment" :
templ . Parse ( mesgTemplates [ "pull_request_comment" ] )
2019-04-20 14:59:08 +02:00
default :
log . Warningf ( "Unknown action: %s for eventHeader %s" , data . Action , eventHeader )
2019-04-13 19:19:24 +02:00
templ . Parse ( "Gitea did something unexpected, seriously wtf was that?! Event: " + eventHeader + " Action: " + data . Action )
2019-04-13 15:25:50 +02:00
}
if err := templ . Execute ( & tpl , data ) ; err != nil {
2019-04-22 20:34:05 +02:00
log . Warningf ( "Failed to generate text-message for eventHeader %v" , eventHeader )
return "" , err
2019-04-13 12:31:28 +02:00
}
2019-04-22 20:34:05 +02:00
return tpl . String ( ) , nil
2019-04-13 12:31:28 +02:00
}