1#!/usr/bin/env python3 2 3""" 4Updates the capability definitions at irc/caps/defs.go 5 6To add a capability, add it to the CAPDEFS list below, 7then run `make capdefs` from the project root. 8""" 9 10import io 11import subprocess 12import sys 13from collections import namedtuple 14 15CapDef = namedtuple("CapDef", ['identifier', 'name', 'url', 'standard']) 16 17CAPDEFS = [ 18 CapDef( 19 identifier="AccountNotify", 20 name="account-notify", 21 url="https://ircv3.net/specs/extensions/account-notify-3.1.html", 22 standard="IRCv3", 23 ), 24 CapDef( 25 identifier="AccountTag", 26 name="account-tag", 27 url="https://ircv3.net/specs/extensions/account-tag-3.2.html", 28 standard="IRCv3", 29 ), 30 CapDef( 31 identifier="AwayNotify", 32 name="away-notify", 33 url="https://ircv3.net/specs/extensions/away-notify-3.1.html", 34 standard="IRCv3", 35 ), 36 CapDef( 37 identifier="Batch", 38 name="batch", 39 url="https://ircv3.net/specs/extensions/batch-3.2.html", 40 standard="IRCv3", 41 ), 42 CapDef( 43 identifier="CapNotify", 44 name="cap-notify", 45 url="https://ircv3.net/specs/extensions/cap-notify-3.2.html", 46 standard="IRCv3", 47 ), 48 CapDef( 49 identifier="ChgHost", 50 name="chghost", 51 url="https://ircv3.net/specs/extensions/chghost-3.2.html", 52 standard="IRCv3", 53 ), 54 CapDef( 55 identifier="EchoMessage", 56 name="echo-message", 57 url="https://ircv3.net/specs/extensions/echo-message-3.2.html", 58 standard="IRCv3", 59 ), 60 CapDef( 61 identifier="ExtendedJoin", 62 name="extended-join", 63 url="https://ircv3.net/specs/extensions/extended-join-3.1.html", 64 standard="IRCv3", 65 ), 66 CapDef( 67 identifier="InviteNotify", 68 name="invite-notify", 69 url="https://ircv3.net/specs/extensions/invite-notify-3.2.html", 70 standard="IRCv3", 71 ), 72 CapDef( 73 identifier="LabeledResponse", 74 name="labeled-response", 75 url="https://ircv3.net/specs/extensions/labeled-response.html", 76 standard="IRCv3", 77 ), 78 CapDef( 79 identifier="Languages", 80 name="draft/languages", 81 url="https://gist.github.com/DanielOaks/8126122f74b26012a3de37db80e4e0c6", 82 standard="proposed IRCv3", 83 ), 84 CapDef( 85 identifier="MessageTags", 86 name="message-tags", 87 url="https://ircv3.net/specs/extensions/message-tags.html", 88 standard="IRCv3", 89 ), 90 CapDef( 91 identifier="MultiPrefix", 92 name="multi-prefix", 93 url="https://ircv3.net/specs/extensions/multi-prefix-3.1.html", 94 standard="IRCv3", 95 ), 96 CapDef( 97 identifier="Relaymsg", 98 name="draft/relaymsg", 99 url="https://github.com/ircv3/ircv3-specifications/pull/417", 100 standard="proposed IRCv3", 101 ), 102 CapDef( 103 identifier="ChannelRename", 104 name="draft/channel-rename", 105 url="https://ircv3.net/specs/extensions/channel-rename", 106 standard="draft IRCv3", 107 ), 108 CapDef( 109 identifier="SASL", 110 name="sasl", 111 url="https://ircv3.net/specs/extensions/sasl-3.2.html", 112 standard="IRCv3", 113 ), 114 CapDef( 115 identifier="ServerTime", 116 name="server-time", 117 url="https://ircv3.net/specs/extensions/server-time-3.2.html", 118 standard="IRCv3", 119 ), 120 CapDef( 121 identifier="SetName", 122 name="setname", 123 url="https://ircv3.net/specs/extensions/setname.html", 124 standard="IRCv3", 125 ), 126 CapDef( 127 identifier="STS", 128 name="sts", 129 url="https://ircv3.net/specs/extensions/sts.html", 130 standard="IRCv3", 131 ), 132 CapDef( 133 identifier="UserhostInNames", 134 name="userhost-in-names", 135 url="https://ircv3.net/specs/extensions/userhost-in-names-3.2.html", 136 standard="IRCv3", 137 ), 138 CapDef( 139 identifier="ZNCSelfMessage", 140 name="znc.in/self-message", 141 url="https://wiki.znc.in/Query_buffers", 142 standard="ZNC vendor", 143 ), 144 CapDef( 145 identifier="EventPlayback", 146 name="draft/event-playback", 147 url="https://github.com/ircv3/ircv3-specifications/pull/362", 148 standard="proposed IRCv3", 149 ), 150 CapDef( 151 identifier="ZNCPlayback", 152 name="znc.in/playback", 153 url="https://wiki.znc.in/Playback", 154 standard="ZNC vendor", 155 ), 156 CapDef( 157 identifier="Nope", 158 name="ergo.chat/nope", 159 url="https://ergo.chat/nope", 160 standard="Ergo vendor", 161 ), 162 CapDef( 163 identifier="Multiline", 164 name="draft/multiline", 165 url="https://github.com/ircv3/ircv3-specifications/pull/398", 166 standard="proposed IRCv3", 167 ), 168 CapDef( 169 identifier="Chathistory", 170 name="draft/chathistory", 171 url="https://github.com/ircv3/ircv3-specifications/pull/393", 172 standard="proposed IRCv3", 173 ), 174 CapDef( 175 identifier="AccountRegistration", 176 name="draft/account-registration", 177 url="https://github.com/ircv3/ircv3-specifications/pull/435", 178 standard="draft IRCv3", 179 ), 180 CapDef( 181 identifier="ExtendedMonitor", 182 name="draft/extended-monitor", 183 url="https://github.com/ircv3/ircv3-specifications/pull/466", 184 standard="draft IRCv3", 185 ), 186] 187 188def validate_defs(): 189 CAPDEFS.sort(key=lambda d: d.name) 190 numCaps = len(CAPDEFS) 191 numNames = len(set(capdef.name for capdef in CAPDEFS)) 192 if numCaps != numNames: 193 raise Exception("defs must have unique names, but found duplicates") 194 numIdentifiers = len(set(capdef.identifier for capdef in CAPDEFS)) 195 if numCaps != numIdentifiers: 196 raise Exception("defs must have unique identifiers, but found duplicates") 197 198def main(): 199 validate_defs() 200 output = io.StringIO() 201 print(""" 202package caps 203 204/* 205 WARNING: this file is autogenerated by `make capdefs` 206 DO NOT EDIT MANUALLY. 207*/ 208 209 210 """, file=output) 211 212 213 numCapabs = len(CAPDEFS) 214 bitsetLen = numCapabs // 32 215 if numCapabs % 32 > 0: 216 bitsetLen += 1 217 print (""" 218const ( 219 // number of recognized capabilities: 220 numCapabs = %d 221 // length of the uint64 array that represents the bitset: 222 bitsetLen = %d 223) 224 """ % (numCapabs, bitsetLen), file=output) 225 226 print("const (", file=output) 227 for capdef in CAPDEFS: 228 print("// %s is the %s capability named \"%s\":" % (capdef.identifier, capdef.standard, capdef.name), file=output) 229 print("// %s" % (capdef.url,), file=output) 230 print("%s Capability = iota" % (capdef.identifier,), file=output) 231 print(file=output) 232 print(")", file=output) 233 234 print("// `capabilityNames[capab]` is the string name of the capability `capab`", file=output) 235 print("""var ( capabilityNames = [numCapabs]string{""", file=output) 236 for capdef in CAPDEFS: 237 print("\"%s\"," % (capdef.name,), file=output) 238 print("})", file=output) 239 240 # run the generated code through `gofmt -s`, which will print it to stdout 241 gofmt = subprocess.Popen(['gofmt', '-s'], stdin=subprocess.PIPE) 242 gofmt.communicate(input=output.getvalue().encode('utf-8')) 243 if gofmt.poll() != 0: 244 print(output.getvalue()) 245 raise Exception("gofmt failed") 246 return 0 247 248if __name__ == '__main__': 249 sys.exit(main()) 250