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  }