~kris/9p

disco

ref: 06b704abda192c8f412b895458e2c4551975a39a disco/DiscordGo/tools/cmd/eventhandlers/main.go -rw-r--r-- 3.0 KiB
06b704ab — Sean Hinchee tweaks 8 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package main

import (
	"bytes"
	"go/format"
	"go/parser"
	"go/token"
	"io/ioutil"
	"log"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
	"text/template"
)

var eventHandlerTmpl = template.Must(template.New("eventHandler").Funcs(template.FuncMap{
	"constName":      constName,
	"isDiscordEvent": isDiscordEvent,
	"privateName":    privateName,
}).Parse(`// Code generated by \"eventhandlers\"; DO NOT EDIT
// See events.go

package discordgo

// Following are all the event types.
// Event type values are used to match the events returned by Discord.
// EventTypes surrounded by __ are synthetic and are internal to DiscordGo.
const ({{range .}}
  {{privateName .}}EventType = "{{constName .}}"{{end}}
)
{{range .}}
// {{privateName .}}EventHandler is an event handler for {{.}} events.
type {{privateName .}}EventHandler func(*Session, *{{.}})

// Type returns the event type for {{.}} events.
func (eh {{privateName .}}EventHandler) Type() string {
  return {{privateName .}}EventType
}
{{if isDiscordEvent .}}
// New returns a new instance of {{.}}.
func (eh {{privateName .}}EventHandler) New() interface{} {
  return &{{.}}{}
}{{end}}
// Handle is the handler for {{.}} events.
func (eh {{privateName .}}EventHandler) Handle(s *Session, i interface{}) {
  if t, ok := i.(*{{.}}); ok {
    eh(s, t)
  }
}

{{end}}
func handlerForInterface(handler interface{}) EventHandler {
  switch v := handler.(type) {
  case func(*Session, interface{}):
    return interfaceEventHandler(v){{range .}}
  case func(*Session, *{{.}}):
    return {{privateName .}}EventHandler(v){{end}}
  }

  return nil
}

func init() { {{range .}}{{if isDiscordEvent .}}
  registerInterfaceProvider({{privateName .}}EventHandler(nil)){{end}}{{end}}
}
`))

func main() {
	var buf bytes.Buffer
	dir := filepath.Dir(".")

	fs := token.NewFileSet()
	parsedFile, err := parser.ParseFile(fs, "events.go", nil, 0)
	if err != nil {
		log.Fatalf("warning: internal error: could not parse events.go: %s", err)
		return
	}

	names := []string{}
	for object := range parsedFile.Scope.Objects {
		names = append(names, object)
	}
	sort.Strings(names)
	eventHandlerTmpl.Execute(&buf, names)

	src, err := format.Source(buf.Bytes())
	if err != nil {
		log.Println("warning: internal error: invalid Go generated:", err)
		src = buf.Bytes()
	}

	err = ioutil.WriteFile(filepath.Join(dir, strings.ToLower("eventhandlers.go")), src, 0644)
	if err != nil {
		log.Fatal(buf, "writing output: %s", err)
	}
}

var constRegexp = regexp.MustCompile("([a-z])([A-Z])")

func constCase(name string) string {
	return strings.ToUpper(constRegexp.ReplaceAllString(name, "${1}_${2}"))
}

func isDiscordEvent(name string) bool {
	switch {
	case name == "Connect", name == "Disconnect", name == "Event", name == "RateLimit", name == "Interface":
		return false
	default:
		return true
	}
}

func constName(name string) string {
	if !isDiscordEvent(name) {
		return "__" + constCase(name) + "__"
	}

	return constCase(name)
}

func privateName(name string) string {
	return strings.ToLower(string(name[0])) + name[1:]
}