discord-protos 1.0.4 → 1.2.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/.github/workflows/update.yml +45 -12
  2. package/.prettierrc.yml +1 -0
  3. package/MANIFEST.in +4 -0
  4. package/README.md +47 -16
  5. package/discord_protos/__init__.py +40 -0
  6. package/discord_protos/discord_kkv_store_value_models/v1/AcknowledgedApplicationDisclosures.proto +22 -0
  7. package/discord_protos/discord_kkv_store_value_models/v1/AcknowledgedApplicationDisclosures_pb2.py +42 -0
  8. package/discord_protos/discord_kkv_store_value_models/v1/ApplicationUserRoleConnection.proto +10 -0
  9. package/discord_protos/discord_kkv_store_value_models/v1/ApplicationUserRoleConnection_pb2.py +40 -0
  10. package/{out → discord_protos/discord_users/v1}/FrecencyUserSettings.proto +31 -5
  11. package/discord_protos/discord_users/v1/FrecencyUserSettings_pb2.py +100 -0
  12. package/discord_protos/discord_users/v1/PreloadedUserSettings.proto +497 -0
  13. package/discord_protos/discord_users/v1/PreloadedUserSettings_pb2.py +208 -0
  14. package/discord_protos/premium_marketing/v1/PremiumMarketingComponentProperties.proto +62 -0
  15. package/discord_protos/premium_marketing/v1/PremiumMarketingComponentProperties_pb2.py +60 -0
  16. package/dist/discord_protos/discord_kkv_store_value_models/v1/AcknowledgedApplicationDisclosures.d.ts +71 -0
  17. package/dist/discord_protos/discord_kkv_store_value_models/v1/AcknowledgedApplicationDisclosures.js +131 -0
  18. package/dist/discord_protos/discord_kkv_store_value_models/v1/ApplicationUserRoleConnection.d.ts +41 -0
  19. package/dist/discord_protos/discord_kkv_store_value_models/v1/ApplicationUserRoleConnection.js +94 -0
  20. package/dist/{proto → discord_protos/discord_users/v1}/FrecencyUserSettings.d.ts +184 -53
  21. package/dist/{proto → discord_protos/discord_users/v1}/FrecencyUserSettings.js +469 -96
  22. package/dist/discord_protos/discord_users/v1/PreloadedUserSettings.d.ts +2035 -0
  23. package/dist/discord_protos/discord_users/v1/PreloadedUserSettings.js +4200 -0
  24. package/dist/{proto → discord_protos}/google/protobuf/timestamp.d.ts +3 -6
  25. package/dist/{proto → discord_protos}/google/protobuf/timestamp.js +11 -11
  26. package/dist/{proto → discord_protos}/google/protobuf/wrappers.d.ts +9 -9
  27. package/dist/{proto → discord_protos}/google/protobuf/wrappers.js +28 -30
  28. package/dist/discord_protos/premium_marketing/v1/PremiumMarketingComponentProperties.d.ts +261 -0
  29. package/dist/discord_protos/premium_marketing/v1/PremiumMarketingComponentProperties.js +558 -0
  30. package/dist/index.d.ts +5 -2
  31. package/dist/index.js +34 -4
  32. package/dist/load.js +144 -8
  33. package/package.json +14 -13
  34. package/pyproject.toml +21 -0
  35. package/requirements.txt +1 -0
  36. package/scripts/parse.js +269 -0
  37. package/scripts/preload.js +17 -0
  38. package/setup.py +42 -0
  39. package/tsconfig.json +6 -4
  40. package/dist/parse.d.ts +0 -35
  41. package/dist/parse.js +0 -175
  42. package/dist/proto/PreloadedUserSettings.d.ts +0 -1022
  43. package/dist/proto/PreloadedUserSettings.js +0 -2235
  44. package/dist/test.d.ts +0 -1
  45. package/dist/test.js +0 -19
  46. package/out/PreloadedUserSettings.proto +0 -240
  47. package/package-lock.json +0 -1755
package/dist/load.js CHANGED
@@ -3,17 +3,153 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const puppeteer_1 = require("puppeteer");
4
4
  const fs_1 = require("fs");
5
5
  const path_1 = require("path");
6
- const script = (0, fs_1.readFileSync)((0, path_1.join)(__dirname, "parse.js"), "utf8");
6
+ const child_process_1 = require("child_process");
7
+ // For the JS template, all we need to do is update the exports at the bottom
8
+ const JS_TEMPLATE = `import { MessageType } from "@protobuf-ts/runtime";
9
+
10
+ /**
11
+ * Supports both node and web environments, replacement of previous Buffer.from() being node-only.
12
+ * This is specific to this package's usage, and not a replacement of Buffer.from() altogether
13
+ */
14
+ const compatBuffer = {
15
+ from: function (input: string | Uint8Array, encoding?: string) {
16
+ if (typeof input === "string" && encoding === "base64") {
17
+ const encodedBytes = atob(input);
18
+ const bytes = new Uint8Array(encodedBytes.length);
19
+ for (let i = 0; i < encodedBytes.length; i++) {
20
+ bytes[i] = encodedBytes.charCodeAt(i);
21
+ }
22
+ return bytes;
23
+ } else if (!encoding && input instanceof Uint8Array) {
24
+ return input;
25
+ }
26
+ throw new Error("Invalid input type.");
27
+ },
28
+ toBase64String: function (buffer: Uint8Array) {
29
+ let encodedBytes = "";
30
+ for (let i = 0; i < buffer.length; i++) {
31
+ encodedBytes += String.fromCharCode(buffer[i]);
32
+ }
33
+ return btoa(encodedBytes);
34
+ },
35
+ };
36
+
37
+ function toBase64(this: MessageType<any>, data) {
38
+ return compatBuffer.toBase64String(compatBuffer.from(this.toBinary(data)));
39
+ }
40
+
41
+ function fromBase64(this: MessageType<any>, base64: string) {
42
+ return this.fromBinary(compatBuffer.from(base64, "base64"));
43
+ }
44
+
45
+ declare module "@protobuf-ts/runtime" {
46
+ interface MessageType<T> {
47
+ toBase64(data: T): string;
48
+ fromBase64(base64: string): T;
49
+ }
50
+ }
51
+
52
+ MessageType.prototype.fromBase64 = fromBase64;
53
+ MessageType.prototype.toBase64 = toBase64;
54
+
55
+ {{ protos_exports }}
56
+ `;
57
+ // For the Python template, we need to update both imports and the __all__ variable, as well as bump the version number
58
+ const PY_TEMPLATE = `from __future__ import annotations
59
+
60
+ from enum import Enum as _Enum
61
+ from typing import TYPE_CHECKING
62
+
63
+ __version__ = '{{ version }}'
64
+
65
+ if TYPE_CHECKING:
66
+ from google.protobuf.message import Message as _Message
67
+
68
+ {{ protos_equals }} = _Message
69
+ else:
70
+ {{ protos_imports }}
71
+
72
+ __all__ = (
73
+ '__version__',
74
+ 'UserSettingsType',
75
+ {{ exports }}
76
+ )
77
+
78
+
79
+ class UserSettingsType(_Enum):
80
+ preloaded_user_settings = 1
81
+ frecency_user_settings = 2
82
+ test_settings = 3
83
+
84
+
85
+ UserSettingsImpl = {
86
+ UserSettingsType.preloaded_user_settings: PreloadedUserSettings,
87
+ UserSettingsType.frecency_user_settings: FrecencyUserSettings,
88
+ UserSettingsType.test_settings: None,
89
+ }
90
+ `;
91
+ // This must be run early
92
+ const PRELOAD_SCRIPT = (0, fs_1.readFileSync)((0, path_1.join)(__dirname, "..", "scripts", "preload.js"), "utf8");
93
+ const PARSE_SCRIPT = (0, fs_1.readFileSync)((0, path_1.join)(__dirname, "..", "scripts", "parse.js"), "utf8");
7
94
  async function main() {
8
- const browser = await puppeteer_1.default.launch({
9
- headless: true,
10
- });
95
+ const browser = await puppeteer_1.default.launch();
11
96
  const page = await browser.newPage();
12
- await page.goto("https://discord.com/app", { waitUntil: "networkidle0" });
13
- const protos = await page.evaluate(`${script}; protos`);
97
+ page.on("console", (msg) => console.debug(msg.text()));
98
+ // Preload script grabs the objects
99
+ await page.evaluateOnNewDocument(PRELOAD_SCRIPT);
100
+ await page.goto("https://canary.discord.com/app", { waitUntil: "networkidle0" });
101
+ const protos = await page.evaluate(`${PARSE_SCRIPT}; protos`);
102
+ await browser.close();
103
+ // Delete all existing files and folders in the discord_protos directory
104
+ const outputs = [(0, path_1.join)(__dirname, "..", "discord_protos"), (0, path_1.join)(__dirname, "..", "src", "discord_protos")];
105
+ for (const output of outputs) {
106
+ if ((0, fs_1.existsSync)(output)) {
107
+ for (const file of (0, fs_1.readdirSync)(output)) {
108
+ try {
109
+ if ((0, fs_1.readdirSync)((0, path_1.join)(output, file)).length > 0) {
110
+ (0, fs_1.rmSync)((0, path_1.join)(output, file), { recursive: true, force: true });
111
+ }
112
+ }
113
+ catch { }
114
+ }
115
+ }
116
+ }
117
+ // Write the protos to disk
118
+ const filenames = [];
14
119
  for (const [name, proto] of Object.entries(protos)) {
15
- (0, fs_1.writeFileSync)((0, path_1.join)(__dirname, "..", "out", name + ".proto"), proto.data);
120
+ const dir = (0, path_1.join)(__dirname, "..", ...proto.package.split("."));
121
+ const filename = (0, path_1.join)(dir, `${name}.proto`);
122
+ filenames.push(filename.replace((0, path_1.join)(__dirname, ".."), ".").replaceAll("\\", "/"));
123
+ // Ensure the directory exists
124
+ if (!(0, fs_1.existsSync)(dir)) {
125
+ (0, fs_1.mkdirSync)(dir, { recursive: true });
126
+ }
127
+ (0, fs_1.writeFileSync)(filename, proto.data);
16
128
  }
17
- await browser.close();
129
+ // Check if we have any changes using git
130
+ const changes = (0, child_process_1.execSync)("git status --porcelain").toString().trim();
131
+ if (!changes.includes(".proto")) {
132
+ console.log("No changes detected, exiting...");
133
+ return;
134
+ }
135
+ const packageJson = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, "..", "package.json"), "utf8"));
136
+ // Bump the version number
137
+ const version = packageJson.version.split(".").map((x) => parseInt(x)).map((x, i) => i === 2 ? x + 1 : x).join(".");
138
+ packageJson.version = version;
139
+ // This is very cursed
140
+ // For protoc to parse any new protos, we have to edit the script in the package.json to include the filenames
141
+ const js = packageJson.scripts.js.split(" ").filter((x) => !x.endsWith(".proto")).join(" ");
142
+ const py = packageJson.scripts.py.split(" ").filter((x) => !x.endsWith(".proto")).join(" ");
143
+ packageJson.scripts.js = `${js} ${filenames.join(" ")}`;
144
+ packageJson.scripts.py = `${py} ${filenames.join(" ")}`;
145
+ (0, fs_1.writeFileSync)((0, path_1.join)(__dirname, "..", "package.json"), JSON.stringify(packageJson, null, 4));
146
+ // Update the JS template
147
+ const jsExports = filenames.map((x) => `export * from "${x.replaceAll("\\", "/").replace(".proto", "")}";`).join("\n");
148
+ (0, fs_1.writeFileSync)((0, path_1.join)(__dirname, "..", "src", "index.ts"), JS_TEMPLATE.replace("{{ protos_exports }}", jsExports));
149
+ // Update the Python template
150
+ const pyExports = Object.keys(protos).map((x) => ` '${x}',`).join("\n");
151
+ const pyImports = filenames.map((x) => ` from ${x.replaceAll("\\", "/").replace("./discord_protos", "").replaceAll("/", ".").replace(".proto", "_pb2")} import *`).join("\n");
152
+ const pyEquals = Object.keys(protos).join(" = ");
153
+ (0, fs_1.writeFileSync)((0, path_1.join)(__dirname, "..", "discord_protos", "__init__.py"), PY_TEMPLATE.replace("{{ version }}", version).replace("{{ exports }}", pyExports).replace("{{ protos_imports }}", pyImports).replace("{{ protos_equals }}", pyEquals));
18
154
  }
19
155
  main();
package/package.json CHANGED
@@ -1,15 +1,14 @@
1
1
  {
2
2
  "name": "discord-protos",
3
- "version": "1.0.4",
3
+ "version": "1.2.43",
4
4
  "description": "A parser for Discord's protobufs",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
- "packageManager": "pnpm@7.14.2",
8
7
  "contributors": [
9
8
  {
10
9
  "name": "dolfies",
11
- "email": "jeyalfie47@gmail.com",
12
- "url": "https://github.com/dolfies"
10
+ "email": "me@dolfi.es",
11
+ "url": "https://dolfi.es"
13
12
  },
14
13
  {
15
14
  "name": "Samuel Scheit",
@@ -17,21 +16,23 @@
17
16
  "url": "https://samuelscheit.com"
18
17
  }
19
18
  ],
19
+ "repository": {
20
+ "url": "https://github.com/discord-userdoccers/discord-protos"
21
+ },
20
22
  "license": "MIT",
21
23
  "scripts": {
22
- "py": "protoc --python_out=./ ./out/*.proto",
23
- "js": "protoc --proto_path=./out/ --ts_out src/proto PreloadedUserSettings.proto FrecencyUserSettings.proto",
24
+ "py": "protoc --proto_path=./discord_protos/ --python_out=discord_protos ./discord_protos/discord_users/v1/PreloadedUserSettings.proto ./discord_protos/discord_users/v1/FrecencyUserSettings.proto ./discord_protos/discord_kkv_store_value_models/v1/ApplicationUserRoleConnection.proto ./discord_protos/discord_kkv_store_value_models/v1/AcknowledgedApplicationDisclosures.proto ./discord_protos/premium_marketing/v1/PremiumMarketingComponentProperties.proto",
25
+ "js": "protoc --proto_path=./discord_protos/ --ts_out src/discord_protos ./discord_protos/discord_users/v1/PreloadedUserSettings.proto ./discord_protos/discord_users/v1/FrecencyUserSettings.proto ./discord_protos/discord_kkv_store_value_models/v1/ApplicationUserRoleConnection.proto ./discord_protos/discord_kkv_store_value_models/v1/AcknowledgedApplicationDisclosures.proto ./discord_protos/premium_marketing/v1/PremiumMarketingComponentProperties.proto",
24
26
  "build": "tsc",
25
- "load": "yarn build && node dist/load.js",
26
- "test": "yarn build && node dist/test.js"
27
+ "load": "npm run build && node dist/load.js"
27
28
  },
28
29
  "devDependencies": {
29
- "@protobuf-ts/plugin": "^2.8.2",
30
- "@protobuf-ts/protoc": "^2.8.2",
31
- "puppeteer": "^19.7.0",
32
- "typescript": "^4.9.5"
30
+ "@protobuf-ts/plugin": "^2.9.6",
31
+ "@protobuf-ts/protoc": "^2.9.6",
32
+ "puppeteer": "^24.6.0",
33
+ "typescript": "^5.8.2"
33
34
  },
34
35
  "dependencies": {
35
- "@protobuf-ts/runtime": "^2.8.2"
36
+ "@protobuf-ts/runtime": "^2.9.6"
36
37
  }
37
38
  }
package/pyproject.toml ADDED
@@ -0,0 +1,21 @@
1
+ [build-system]
2
+ requires = ["setuptools", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [tool.black]
6
+ line-length = 125
7
+ skip-string-normalization = true
8
+
9
+ [tool.pyright]
10
+ include = ["discord_protos"]
11
+ exclude = [
12
+ "**/__pycache__",
13
+ "src",
14
+ "node_modules",
15
+ ]
16
+ reportUnnecessaryTypeIgnoreComment = "warning"
17
+ reportUnusedImport = "error"
18
+ reportShadowedImports = false
19
+ pythonVersion = "3.8"
20
+ typeCheckingMode = "basic"
21
+ useLibraryCodeForTypes = true
@@ -0,0 +1 @@
1
+ protobuf
@@ -0,0 +1,269 @@
1
+ // Map the type ints to their names
2
+ const ScalarType = {
3
+ 1: "double",
4
+ 2: "float",
5
+ 3: "int64",
6
+ 4: "uint64",
7
+ 5: "int32",
8
+ 6: "fixed64",
9
+ 7: "fixed32",
10
+ 8: "bool",
11
+ 9: "string",
12
+ 12: "bytes",
13
+ 13: "uint32",
14
+ 15: "sfixed32",
15
+ 16: "sfixed64",
16
+ 17: "sint32",
17
+ 18: "sint64",
18
+ };
19
+ const RepeatType = {
20
+ NO: 0,
21
+ PACKED: 1,
22
+ UNPACKED: 2,
23
+ };
24
+
25
+ function parseType(field) {
26
+ // We extract the actual field if possible
27
+ if (typeof field === "function") {
28
+ field = field();
29
+ // If it's a real type, we just return it
30
+ } else if (typeof field === "number") {
31
+ return [ScalarType[field], []];
32
+ }
33
+
34
+ var type,
35
+ structs = [];
36
+
37
+ // The kind gives us clues on how to find the type
38
+ switch (field.kind) {
39
+ case "message":
40
+ type = field.T().typeName;
41
+ if (type.startsWith("discord")) {
42
+ [, type] = parseName(type);
43
+ }
44
+ break;
45
+ case "scalar":
46
+ type = ScalarType[field.T];
47
+ break;
48
+ case "map":
49
+ type = `map<${parseType(field.K)[0]}, ${parseType(field.V)[0]}>`;
50
+ break;
51
+ case "enum":
52
+ [, type] = parseName(field.T()[0]);
53
+ break;
54
+ default:
55
+ throw new Error(`Unknown field type: ${field?.kind || field}`);
56
+ }
57
+
58
+ // Now we lazily discover any protos in the fields
59
+ for (let t of [field.T, field.K, field.V]) {
60
+ t = t?.T || t;
61
+
62
+ if (typeof t === "function" && (!t().typeName || t().typeName.startsWith("discord_protos"))) {
63
+ t = t();
64
+ if (Array.isArray(t)) {
65
+ structs.push(parseEnum(t));
66
+ } else {
67
+ const extraStruct = parseProto(t);
68
+ structs.push(...(extraStruct.structs || []));
69
+ delete extraStruct.structs;
70
+ structs.push(extraStruct);
71
+ }
72
+ }
73
+ }
74
+
75
+ return [type, structs];
76
+ }
77
+
78
+ function parseName(name) {
79
+ const split = name.split(".");
80
+ return [split.slice(0, -1).join("."), split.slice(-1)[0]];
81
+ }
82
+
83
+ function convertCase(str) {
84
+ // This converts standard EnumType case to ENUM_TYPE
85
+ // it must support the special case SlayerSDKReceive to SLAYER_SDK_RECEIVE
86
+ return str
87
+ // HACK: I can't think of another way to fix this
88
+ .replace("DMs", "Dms")
89
+ .replace(/([a-z])([A-Z])/g, "$1_$2")
90
+ .replace(/([A-Z])([A-Z][a-z])/g, "$1_$2")
91
+ .replace(/([a-z])(\d)/g, "$1_$2")
92
+ .replace(/([A-Z]+)(?=[A-Z][a-z])/g, "$1_")
93
+ .toUpperCase();
94
+ }
95
+
96
+ function camelToSnake(str) {
97
+ return str.replace(/(([a-z])(?=[A-Z][a-zA-Z])|([A-Z])(?=[A-Z][a-z]))/g,'$1_').toLowerCase()
98
+ }
99
+
100
+ function flattenField(field) {
101
+ const [type, structs] = parseType(field);
102
+ return [
103
+ {
104
+ number: field.no,
105
+ name: field.name,
106
+ kind: field.kind,
107
+ type: type,
108
+ oneof: field.oneof,
109
+ optional: field.opt,
110
+ repeated: Boolean(field.repeat),
111
+ unpacked: field.repeat === RepeatType.UNPACKED,
112
+ },
113
+ structs,
114
+ ];
115
+ }
116
+
117
+ function parseEnum(enun) {
118
+ const [name, data] = enun;
119
+
120
+ // Protobuf enum values conventionally have a prefix of NAME_ and we must add that back
121
+ const [, formattedName] = parseName(name);
122
+ const prefix = convertCase(formattedName) + "_";
123
+
124
+ return {
125
+ name: formattedName,
126
+ kind: "enum",
127
+ values: Object.entries(data)
128
+ .filter(([k, _]) => isNaN(Number(k)))
129
+ .map(([k, v]) => ({
130
+ // Discord shitcode sometimes fails to strip the prefix on the special case
131
+ // so we check if it already has it
132
+ name: k.startsWith(prefix) ? k : prefix + k,
133
+ value: v,
134
+ })),
135
+ };
136
+ }
137
+
138
+ function parseProto(proto) {
139
+ const fields = [];
140
+ const structs = [];
141
+ proto.fields.forEach(function (field) {
142
+ const [f, s] = flattenField(field);
143
+ fields.push(f);
144
+ structs.push(...s);
145
+ });
146
+
147
+ const seen = new Set();
148
+ const [package, name] = parseName(proto.typeName);
149
+ return {
150
+ package,
151
+ name,
152
+ kind: "message",
153
+ fields: fields,
154
+ structs: structs.filter((v) => (seen.has(v.name) ? false : seen.add(v.name))),
155
+ };
156
+ }
157
+
158
+ function extractProtos() {
159
+ const results = {};
160
+
161
+ // Populated by preload.js
162
+ for (const proto of window.protoObjects) {
163
+ if (!proto?.typeName?.startsWith?.("discord_protos")) continue;
164
+ const [, name] = parseName(proto.typeName);
165
+ console.log(`Parsing ${name}...`);
166
+ results[name] = parseProto(proto);
167
+ }
168
+
169
+ // Remove every proto that is mentioned in another proto
170
+ for (const proto of Object.values(results)) {
171
+ for (const struct of proto.structs) {
172
+ delete results[struct.name];
173
+ }
174
+ }
175
+
176
+ return results;
177
+ }
178
+
179
+ function createProtoField(field) {
180
+ if (!field.repeated && field.unpacked)
181
+ throw new Error(`Field ${field.name} is not repeated but has unpacked set`);
182
+ return `${field.optional ? "optional " : field.repeated ? "repeated " : ""}${field.type} ${field.name} = ${field.number}${field.unpacked ? " [packed = false]" : ""};`;
183
+ }
184
+
185
+ function createProtoFile(proto) {
186
+ const lines = [`syntax = "proto3";\n`, `package ${proto.package};\n`, `message ${proto.name} {`];
187
+
188
+ proto.structs.forEach((struct) => {
189
+ lines.push(` ${struct.kind} ${struct.name} {`);
190
+
191
+ switch (struct.kind) {
192
+ case "enum":
193
+ struct.values.forEach((value) => {
194
+ lines.push(` ${value.name.toUpperCase()} = ${value.value};`);
195
+ });
196
+ break;
197
+ case "message":
198
+ // Group fields by oneof if applicable
199
+ const oneofGroups = new Map();
200
+ const normalFields = [];
201
+
202
+ struct.fields.forEach((field) => {
203
+ if (field.oneof) {
204
+ if (!oneofGroups.has(field.oneof)) {
205
+ oneofGroups.set(field.oneof, []);
206
+ }
207
+ oneofGroups.get(field.oneof).push(field);
208
+ } else {
209
+ normalFields.push(field);
210
+ }
211
+ });
212
+
213
+ oneofGroups.forEach((fields, oneofName) => {
214
+ lines.push(` oneof ${camelToSnake(oneofName)} {`);
215
+ fields.forEach((field) => {
216
+ lines.push(` ${createProtoField(field)}`);
217
+ });
218
+ lines.push(` }`);
219
+ });
220
+
221
+ normalFields.forEach((field) => {
222
+ lines.push(` ${createProtoField(field)}`);
223
+ });
224
+ break;
225
+ default:
226
+ throw new Error(`Unknown struct kind: ${struct.kind}`);
227
+ }
228
+
229
+ lines.push(` }\n`);
230
+ });
231
+
232
+ const oneofGroups = new Map();
233
+
234
+ proto.fields.forEach((field) => {
235
+ if (field.oneof) {
236
+ if (!oneofGroups.has(field.oneof)) {
237
+ oneofGroups.set(field.oneof, []);
238
+ }
239
+ oneofGroups.get(field.oneof).push(createProtoField(field));
240
+ } else {
241
+ lines.push(` ${createProtoField(field)}`);
242
+ }
243
+ });
244
+
245
+ oneofGroups.forEach((fields, oneofName) => {
246
+ lines.push(` oneof ${camelToSnake(oneofName)} {`);
247
+ fields.forEach(field => lines.push(` ${field}`));
248
+ lines.push(` }\n`);
249
+ });
250
+
251
+ // Check if we're using the funny Google well-knowns and insert an import statement (I love Discord)
252
+ if (lines.some((line) => line.includes("google.protobuf"))) {
253
+ lines.splice(1, 0, `import "google/protobuf/wrappers.proto";\nimport "google/protobuf/timestamp.proto";\n`);
254
+ }
255
+
256
+ lines.push("}\n");
257
+ return lines.join("\n");
258
+ }
259
+
260
+ const protos = extractProtos();
261
+ for (const [key, proto] of Object.entries(protos)) {
262
+ const data = createProtoFile(proto);
263
+ protos[key].data = data;
264
+ if (window.DiscordNative?.fileManager) {
265
+ window.DiscordNative.fileManager.saveWithDialog(data, `${proto.name}.proto`);
266
+ } else {
267
+ console.log(data);
268
+ }
269
+ }
@@ -0,0 +1,17 @@
1
+ window.protoObjects = [];
2
+ Object.defineProperty(Object.prototype, "typeName", {
3
+ configurable: true,
4
+
5
+ set(v) {
6
+ if (this.internalBinaryRead != null) {
7
+ window.protoObjects.push(this);
8
+ }
9
+
10
+ Object.defineProperty(this, "typeName", {
11
+ value: v,
12
+ configurable: true,
13
+ enumerable: true,
14
+ writable: true
15
+ });
16
+ }
17
+ });
package/setup.py ADDED
@@ -0,0 +1,42 @@
1
+ from setuptools import setup
2
+ import re
3
+
4
+ with open('requirements.txt') as f:
5
+ requirements = f.read().splitlines()
6
+
7
+ with open('discord_protos/__init__.py') as f:
8
+ version = re.search(r'^__version__\s*=\s*[\'"]([^\'"]*)[\'"]', f.read(), re.MULTILINE).group(1)
9
+
10
+ with open('README.md') as f:
11
+ readme = f.read()
12
+
13
+ setup(
14
+ name='discord-protos',
15
+ author='Dolfies',
16
+ url='https://github.com/dolfies/discord-protos',
17
+ project_urls={
18
+ 'Issue tracker': 'https://github.com/dolfies/discord-protos/issues',
19
+ },
20
+ version=version,
21
+ packages=['discord_protos'],
22
+ license='MIT',
23
+ description='Discord user settings protobufs.',
24
+ long_description=readme,
25
+ long_description_content_type='text/markdown',
26
+ include_package_data=True,
27
+ install_requires=requirements,
28
+ python_requires='>=3.8.0',
29
+ classifiers=[
30
+ 'License :: OSI Approved :: MIT License',
31
+ 'Natural Language :: English',
32
+ 'Operating System :: OS Independent',
33
+ 'Programming Language :: Python :: 3.8',
34
+ 'Programming Language :: Python :: 3.9',
35
+ 'Programming Language :: Python :: 3.10',
36
+ 'Programming Language :: Python :: 3.11',
37
+ 'Topic :: Internet',
38
+ 'Topic :: Software Development :: Libraries',
39
+ 'Topic :: Software Development :: Libraries :: Python Modules',
40
+ 'Topic :: Utilities',
41
+ ],
42
+ )
package/tsconfig.json CHANGED
@@ -1,10 +1,12 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "target": "ES2020",
3
+ "target": "ESNext",
4
4
  "module": "commonjs",
5
5
  "allowJs": true,
6
6
  "declaration": true,
7
- "outDir": "./dist",
8
- "rootDir": "./src",
9
- }
7
+ "strictNullChecks": true,
8
+ "outDir": "./dist",
9
+ "rootDir": "./src"
10
+ },
11
+ "include": ["src/*.ts", "src/*/*.ts"],
10
12
  }
package/dist/parse.d.ts DELETED
@@ -1,35 +0,0 @@
1
- declare function parseType(field: any): any;
2
- declare function parseName(name: any): any;
3
- declare function flattenField(field: any): any[];
4
- declare function parseEnum(enun: any): {
5
- name: any;
6
- kind: string;
7
- values: {
8
- name: string;
9
- value: any;
10
- }[];
11
- };
12
- declare function parseProto(proto: any): {
13
- name: any;
14
- kind: string;
15
- fields: any[];
16
- structs: any[];
17
- };
18
- declare function extractProtos(): {};
19
- declare function createProtoField(field: any): string;
20
- declare function createProtoFile(proto: any): string;
21
- declare function getModules(str: any): any;
22
- declare function filterMap(arr: any, callback: any): any;
23
- declare const REAL_TYPES: {
24
- 1: string;
25
- 2: string;
26
- 3: string;
27
- 4: string;
28
- 5: string;
29
- 6: string;
30
- 8: string;
31
- 9: string;
32
- 12: string;
33
- 13: string;
34
- };
35
- declare const protos: {};