github.com/tada-team/tdproto@v1.51.57/codegen/sphinx/json_index/main.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "os" 6 "sort" 7 "strings" 8 "text/template" 9 "unicode" 10 11 "github.com/tada-team/tdproto/codegen" 12 ) 13 14 func main() { 15 tdprotoInfo, err := codegen.ParseTdproto() 16 if err != nil { 17 panic(err) 18 } 19 20 err = generateRstJson(tdprotoInfo.TdModels) 21 if err != nil { 22 panic(err) 23 } 24 } 25 26 var jsTypesMap = map[string]string{ 27 "string": "string", 28 "int": "number", 29 "int64": "number", 30 "uint16": "number", 31 "uint": "number", 32 "bool": "boolean", 33 "interface{}": "any", 34 "ISODateTimeString": "string", 35 "time.Time": "string", 36 } 37 38 type rstJsonField struct { 39 codegen.TdStructField 40 IsJsonPrimitive bool 41 TypeStr string 42 } 43 44 func (r rstJsonField) GetModifiers() string { 45 if r.TdStructField.IsOmitEmpty { 46 return " omitempty" 47 } 48 49 if r.TdStructField.IsPointer { 50 return " nullable" 51 } 52 53 return "" 54 } 55 56 type rstJsonStruct struct { 57 codegen.TdStruct 58 Fields []rstJsonField 59 } 60 61 var jsonTemplate = template.Must(template.New("rstJson").Parse(` 62 .. tdproto:struct:: {{.TdStruct.Name}} 63 :tdpackage: tdmodels 64 65 {{.TdStruct.Help}} 66 {{range $field := .Fields}} 67 :field {{$field.TdStructField.JsonName}} {{$field.TypeStr}}{{.GetModifiers}}: {{$field.TdStructField.Help}}{{end}} 68 `)) 69 70 var enumTemplate = template.Must(template.New("rstEnum").Parse(` 71 .. tdproto:enum:: {{.Name}} 72 :tdpackage: tdmodels 73 74 **Possible values**: 75 {{range $value := .Values}} 76 * {{$value}}{{end}} 77 78 `)) 79 80 var typeAliasTemplate = template.Must(template.New("rstType").Parse(` 81 .. tdproto:type:: {{.Name}} 82 :tdpackage: tdmodels 83 84 {{if .Help}} 85 {{.Help}} 86 {{end}} 87 **Base Type**: {{.BaseType}}{{if .IsArray}} 88 89 **Is array**{{end}} 90 `)) 91 92 var httpQueryTemplate = template.Must(template.New("rstQuery").Parse(` 93 .. _tdproto-{{- .Name}}Query: 94 95 {{.Name}} 96 ------------------------------------------------------------- 97 {{if .Help}} 98 {{.Help}}{{end}} 99 {{range $paramName, $help := .ParamsNamesAndHelp}} 100 * ` + "``" + "{{$paramName}}" + "``" + ` - {{$help}}{{end}} 101 `)) 102 103 func isEventStruct(structName string, tdprotoInfo *codegen.TdPackage) bool { 104 if structName == "BaseEvent" { 105 return true 106 } 107 108 _, isEvent := tdprotoInfo.TdEvents[structName] 109 return isEvent 110 } 111 112 func generateRstJson(tdprotoInfo *codegen.TdPackage) error { 113 114 enumedTypeAliases := make(map[string]string) 115 116 fmt.Fprintln(os.Stdout, "\nEnums index\n============================") 117 enumsList := tdprotoInfo.GetEnums() 118 sort.Slice(enumsList, func(i, j int) bool { 119 return strings.ToLower(enumsList[i].Name) < strings.ToLower(enumsList[j].Name) 120 }) 121 for _, enum := range enumsList { 122 err := enumTemplate.Execute(os.Stdout, enum) 123 if err != nil { 124 return err 125 } 126 enumedTypeAliases[enum.Name] = "" 127 } 128 129 fmt.Fprintln(os.Stdout, "\nType aliases\n============================") 130 var typesList []codegen.TdType 131 for _, someType := range tdprotoInfo.TdTypes { 132 typesList = append(typesList, someType) 133 } 134 sort.Slice(typesList, func(i, j int) bool { 135 return strings.ToLower(typesList[i].Name) < strings.ToLower(typesList[j].Name) 136 }) 137 for _, typeAlias := range typesList { 138 _, isEnumed := enumedTypeAliases[typeAlias.Name] 139 if isEnumed { 140 continue 141 } 142 143 err := typeAliasTemplate.Execute(os.Stdout, typeAlias) 144 if err != nil { 145 return err 146 } 147 } 148 149 var jsonObjects []rstJsonStruct 150 151 for _, tdStruct := range tdprotoInfo.TdStructs { 152 if tdStruct.Help == "" { 153 // Do not print structures without help 154 continue 155 } 156 157 if unicode.IsLower([]rune(tdStruct.Name)[0]) { 158 // Do not print private structs 159 continue 160 } 161 162 if isEventStruct(tdStruct.Name, tdprotoInfo) { 163 continue 164 } 165 166 if tdStruct.IsEventParams(tdprotoInfo) { 167 continue 168 } 169 170 newRstJson := rstJsonStruct{ 171 TdStruct: tdStruct, 172 } 173 174 fieldMissingHelp := false 175 176 for _, field := range tdStruct.GetAllJsonFields(tdprotoInfo) { 177 if field.IsNotSerialized { 178 continue 179 } 180 181 if field.Help == "" { 182 fieldMissingHelp = true 183 break 184 } 185 186 goFieldType := field.TypeStr 187 188 var jsTypeStr string 189 primitiveType, isJsonPrimitive := jsTypesMap[goFieldType] 190 if isJsonPrimitive { 191 jsTypeStr = primitiveType 192 } else { 193 jsTypeStr = fmt.Sprintf("`tdproto-%s`", goFieldType) 194 } 195 196 if field.IsList { 197 jsTypeStr = fmt.Sprintf("array[%s]", jsTypeStr) 198 } 199 200 newRstJson.Fields = append(newRstJson.Fields, rstJsonField{ 201 TdStructField: field, 202 IsJsonPrimitive: isJsonPrimitive, 203 TypeStr: jsTypeStr, 204 }) 205 } 206 207 if fieldMissingHelp { 208 continue 209 } 210 211 jsonObjects = append(jsonObjects, newRstJson) 212 } 213 214 sort.Slice(jsonObjects, func(i, j int) bool { 215 return strings.ToLower(jsonObjects[i].Name) < strings.ToLower(jsonObjects[j].Name) 216 }) 217 218 fmt.Fprintln(os.Stdout, "\nJSON objects index\n============================") 219 220 for _, object := range jsonObjects { 221 err := jsonTemplate.Execute(os.Stdout, object) 222 if err != nil { 223 return err 224 } 225 } 226 227 fmt.Fprintln(os.Stdout, "\nHTTP Queries\n============================") 228 229 for _, query := range tdprotoInfo.TdQueries { 230 err := httpQueryTemplate.Execute(os.Stdout, query) 231 if err != nil { 232 return err 233 } 234 } 235 236 return nil 237 }