generator-discord 1.2.3 → 1.2.5

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.
package/README.md CHANGED
@@ -25,6 +25,7 @@ Generate a basic starter project for a new Discord-bot in your favorite programm
25
25
  - TypeScript
26
26
  - JavaScript
27
27
  - Python
28
+ - Rust
28
29
 
29
30
  ### Your favorite is not listed?
30
31
 
package/app/index.d.ts CHANGED
@@ -1,4 +1,12 @@
1
+ /// <reference types="node" />
1
2
  import Generator from 'yeoman-generator';
3
+ type BotType = 'typescript' | 'javascript' | 'python' | 'rust';
4
+ interface Answers {
5
+ botName: string;
6
+ botType: BotType;
7
+ botToken: string;
8
+ openWithCode: boolean;
9
+ }
2
10
  export default class DiscordGenerator extends Generator {
3
11
  private answers;
4
12
  constructor(args: string | string[], options: Generator.GeneratorOptions);
@@ -7,4 +15,6 @@ export default class DiscordGenerator extends Generator {
7
15
  writing(): void;
8
16
  install(): Promise<void>;
9
17
  end(): Promise<void>;
18
+ _replaceWords(content: Buffer, answers: Answers): string;
10
19
  }
20
+ export {};
package/app/index.js CHANGED
@@ -16,13 +16,13 @@ const yeoman_generator_1 = __importDefault(require("yeoman-generator"));
16
16
  const path_1 = __importDefault(require("path"));
17
17
  const TEMPLATE_DIR = '../templates/';
18
18
  const USER_DIR = '.';
19
- const OPEN = '<%= ';
20
- const CLOSE = ' %>';
21
- const BOT_NAME = 'bot-name';
22
- const BOT_TOKEN = 'bot-token';
19
+ const BOT_NAME = /<%= bot-name %>/g;
20
+ const BOT_TOKEN = /<%= bot-token %>/g;
21
+ const BOT_NAME_RUST = /bot_name/g;
23
22
  class DiscordGenerator extends yeoman_generator_1.default {
24
23
  constructor(args, options) {
25
24
  super(args, options);
25
+ this.answers = {};
26
26
  }
27
27
  prompting() {
28
28
  return __awaiter(this, void 0, void 0, function* () {
@@ -33,7 +33,7 @@ class DiscordGenerator extends yeoman_generator_1.default {
33
33
  name: 'botName',
34
34
  message: 'Your Discord Bot name:',
35
35
  default: 'my-bot',
36
- validate: (input) => new RegExp("^(?:@[a-z0-9-*~][a-z0-9-*._~]*/)?[a-z0-9-~][a-z0-9-._~]*$").test(input)
36
+ validate: (input) => new RegExp('^(?:@[a-z0-9-*~][a-z0-9-*._~]*/)?[a-z0-9-~][a-z0-9-._~]*$').test(input)
37
37
  ? true
38
38
  : 'Invalid bot name. Please use only lowercase letters, numbers, and hyphens. Must start with a letter.'
39
39
  },
@@ -53,7 +53,11 @@ class DiscordGenerator extends yeoman_generator_1.default {
53
53
  {
54
54
  name: 'New Discord Bot (Python)',
55
55
  value: 'python'
56
- }
56
+ },
57
+ {
58
+ name: 'New Discord Bot (Rust)',
59
+ value: 'rust'
60
+ },
57
61
  ]
58
62
  },
59
63
  {
@@ -66,25 +70,21 @@ class DiscordGenerator extends yeoman_generator_1.default {
66
70
  });
67
71
  }
68
72
  logo() {
69
- this.log(" \x1b[36m_____ _ _ \x1b[31m_ ");
70
- this.log(" \x1b[36m| __ \\(_) | | \x1b[31m(_) ");
71
- this.log(" \x1b[36m| | | |_ ___ ___ ___ _ __ __| | \x1b[33m_ ___ ");
72
- this.log(" \x1b[36m| | | | / __|/ __/ _ \\| '__/ _` | \x1b[33m| / __|");
73
- this.log(" \x1b[36m| |__| | \\__ \\ (_| (_) | | | (_| |\x1b[37m_\x1b[32m| \\__ \\");
74
- this.log(" \x1b[36m|_____/|_|___/\\___\\___/|_| \\__,_\x1b[37m(_) \x1b[32m|___/");
75
- this.log(" \x1b[34m_/ | ");
76
- this.log(" \x1b[35m|__/ ");
77
- this.log("\x1b[0m");
73
+ this.log(' \x1b[36m_____ _ _ \x1b[31m_ ');
74
+ this.log(' \x1b[36m| __ \\(_) | | \x1b[31m(_) ');
75
+ this.log(' \x1b[36m| | | |_ ___ ___ ___ _ __ __| | \x1b[33m_ ___ ');
76
+ this.log(' \x1b[36m| | | | / __|/ __/ _ \\| \'__/ _` | \x1b[33m| / __|');
77
+ this.log(' \x1b[36m| |__| | \\__ \\ (_| (_) | | | (_| |\x1b[37m_\x1b[32m| \\__ \\');
78
+ this.log(' \x1b[36m|_____/|_|___/\\___\\___/|_| \\__,_\x1b[37m(_) \x1b[32m|___/');
79
+ this.log(' \x1b[34m_/ | ');
80
+ this.log(' \x1b[35m|__/ ');
81
+ this.log('\x1b[0m');
78
82
  }
79
83
  writing() {
80
84
  this.sourceRoot(path_1.default.join(__dirname, TEMPLATE_DIR + this.answers.botType));
81
85
  ['.'].forEach((path) => {
82
- const replaceWords = (answers, content) => [
83
- [BOT_NAME, this.answers.botName],
84
- [BOT_TOKEN, this.answers.botToken]
85
- ].reduce((acc, [templateWord, userAnswer]) => acc.replace(new RegExp(`${OPEN}${templateWord}${CLOSE}`, 'g'), userAnswer), content.toString());
86
86
  this.fs.copy(this.templatePath(path), this.destinationPath(USER_DIR, this.answers.botName, path), {
87
- process: (content) => replaceWords(this.answers, content)
87
+ process: (content) => this._replaceWords(content, this.answers)
88
88
  });
89
89
  });
90
90
  }
@@ -124,6 +124,16 @@ class DiscordGenerator extends yeoman_generator_1.default {
124
124
  }
125
125
  });
126
126
  }
127
+ _replaceWords(content, answers) {
128
+ if (answers.botType === 'rust') {
129
+ return content.toString()
130
+ .replace(BOT_TOKEN, answers.botToken)
131
+ .replace(BOT_NAME_RUST, answers.botName);
132
+ }
133
+ return content.toString()
134
+ .replace(BOT_TOKEN, answers.botToken)
135
+ .replace(BOT_NAME, answers.botName);
136
+ }
127
137
  }
128
138
  exports.default = DiscordGenerator;
129
139
  //# sourceMappingURL=index.js.map
package/app/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,wEAAyC;AACzC,gDAAwB;AAExB,MAAM,YAAY,GAAG,eAAe,CAAC;AACrC,MAAM,QAAQ,GAAG,GAAG,CAAC;AAErB,MAAM,QAAQ,GAAG,kBAAkB,CAAC;AACpC,MAAM,SAAS,GAAG,mBAAmB,CAAC;AAEtC,MAAM,aAAa,GAAG,WAAW,CAAC;AAYlC,MAAqB,gBAAiB,SAAQ,0BAAS;IAGtD,YAAY,IAAuB,EAAE,OAAmC;QACvE,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAHd,YAAO,GAAY,EAAa,CAAC;IAIzC,CAAC;IAEK,SAAS;;YACd,IAAI,CAAC,IAAI,EAAE,CAAC;YACZ,IAAI,CAAC,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC;gBAChC;oBACC,IAAI,EAAE,OAAO;oBACb,IAAI,EAAE,SAAS;oBACf,OAAO,EAAE,wBAAwB;oBACjC,OAAO,EAAE,QAAQ;oBACjB,QAAQ,EAAE,CAAC,KAAa,EAAoB,EAAE,CAC7C,IAAI,MAAM,CAAC,2DAA2D,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;wBAClF,CAAC,CAAC,IAAI;wBACN,CAAC,CAAC,sGAAsG;iBAC1G;gBACD;oBACC,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,SAAS;oBACf,OAAO,EAAE,6CAA6C;oBACtD,OAAO,EAAE;wBACR;4BACC,IAAI,EAAE,8BAA8B;4BACpC,KAAK,EAAE,YAAY;yBACnB;wBACD;4BACC,IAAI,EAAE,8BAA8B;4BACpC,KAAK,EAAE,YAAY;yBACnB;wBACD;4BACC,IAAI,EAAE,0BAA0B;4BAChC,KAAK,EAAE,QAAQ;yBACf;wBACD;4BACC,IAAI,EAAE,wBAAwB;4BAC9B,KAAK,EAAE,MAAM;yBACb;qBACD;iBACD;gBACD;oBACC,IAAI,EAAE,OAAO;oBACb,IAAI,EAAE,UAAU;oBAChB,OAAO,EAAE,gDAAgD;oBACzD,OAAO,EAAE,gBAAgB;iBACzB;aACD,CAAC,CAAC;QACJ,CAAC;KAAA;IAED,IAAI;QACH,IAAI,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAC;QACxE,IAAI,CAAC,GAAG,CAAC,8DAA8D,CAAC,CAAC;QACzE,IAAI,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAC;QACxE,IAAI,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAC;QAC1E,IAAI,CAAC,GAAG,CAAC,yEAAyE,CAAC,CAAC;QACpF,IAAI,CAAC,GAAG,CAAC,wEAAwE,CAAC,CAAC;QACnF,IAAI,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;QAChE,IAAI,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;QAChE,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACrB,CAAC;IAED,OAAO;QACN,IAAI,CAAC,UAAU,CAAC,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;QAC3E,CAAC,GAAG,CAAC,CAAC,OAAO,CACZ,CAAC,IAAY,EAAE,EAAE;YAChB,IAAI,CAAC,EAAE,CAAC,IAAI,CACX,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EACvB,IAAI,CAAC,eAAe,CACnB,QAAQ,EACR,IAAI,CAAC,OAAO,CAAC,OAAO,EACpB,IAAI,CACJ,EACD;gBACC,OAAO,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC;aACvE,CACD,CAAC;QACH,CAAC,CACD,CAAC;IACH,CAAC;IAEK,OAAO;;YACZ,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACb,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,YAAY,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,YAAY,EAAE;gBACnF,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC9E,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC;gBACnD,IAAG,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,YAAY,EAAE;oBACzC,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;iBACxD;aACD;YAED,IAAI,CAAC,GAAG,CAAC,mBAAmB,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,GAAG,oBAAoB,CAAC,CAAC;QAE7E,CAAC;KAAA;IAEK,GAAG;;YACR,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC;gBAChC,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,+DAA+D;gBACxE,OAAO,EAAE;oBACR;wBACC,IAAI,EAAE,kBAAkB;wBACxB,KAAK,EAAE,IAAI;qBACX;oBACD;wBACC,IAAI,EAAE,MAAM;wBACZ,KAAK,EAAE,KAAK;qBACZ;iBACD;aACD,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACb,IAAI,MAAM,IAAI,MAAM,CAAC,YAAY,EAAE;gBAClC,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,eAAe,CAC9C,QAAQ,EACR,IAAI,CAAC,OAAO,CAAC,OAAO,CACpB,CAAC,CAAC,CAAC;aACJ;QACF,CAAC;KAAA;IAED,aAAa,CAAC,OAAe,EAAE,OAAgB;QAC9C,IAAG,OAAO,CAAC,OAAO,KAAK,MAAM,EAAE;YAC9B,OAAO,OAAO,CAAC,QAAQ,EAAE;iBACvB,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,QAAQ,CAAC;iBACpC,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;SAC1C;QAED,OAAO,OAAO,CAAC,QAAQ,EAAE;aACvB,OAAO,CAAC,SAAS,EAAC,OAAO,CAAC,QAAQ,CAAC;aACnC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;CACD;AArID,mCAqIC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "generator-discord",
3
3
  "displayName": "Generator-Discord",
4
- "version": "1.2.3",
4
+ "version": "1.2.5",
5
5
  "main": "./app/index.js",
6
6
  "description": "Yeoman generator for Discord.js",
7
7
  "keywords": [
@@ -14,6 +14,7 @@
14
14
  "build": "tsc",
15
15
  "watch": "tsc -w",
16
16
  "test": "vitest run",
17
+ "lint": "eslint src test --ext .ts",
17
18
  "debug": "npx --node-arg=--inspect yo discord",
18
19
  "clean": "npx rimraf app && npx rimraf node_modules"
19
20
  },
@@ -35,11 +36,14 @@
35
36
  },
36
37
  "homepage": "https://github.com/emilkrebs/Generator-Discord",
37
38
  "dependencies": {
38
- "typescript": "^5.1.6",
39
39
  "yeoman-generator": "^5.9.0"
40
40
  },
41
41
  "devDependencies": {
42
- "vitest": "^0.34.2",
42
+ "@typescript-eslint/eslint-plugin": "^6.6.0",
43
+ "@typescript-eslint/parser": "^6.6.0",
44
+ "eslint": "^8.49.0",
45
+ "typescript": "^5.2.2",
46
+ "vitest": "^0.34.4",
43
47
  "yeoman-test": "^7.4.0"
44
48
  }
45
49
  }
package/src/index.ts CHANGED
@@ -4,155 +4,152 @@ import path from 'path';
4
4
  const TEMPLATE_DIR = '../templates/';
5
5
  const USER_DIR = '.';
6
6
 
7
- const OPEN = '<%= ';
8
- const CLOSE = ' %>';
7
+ const BOT_NAME = /<%= bot-name %>/g;
8
+ const BOT_TOKEN = /<%= bot-token %>/g;
9
9
 
10
- const BOT_NAME = 'bot-name';
11
- const BOT_TOKEN = 'bot-token';
10
+ const BOT_NAME_RUST = /bot_name/g;
11
+
12
+ type BotType = 'typescript' | 'javascript' | 'python' | 'rust';
12
13
 
13
14
  interface Answers {
14
15
  botName: string;
15
- botType: string;
16
+ botType: BotType;
16
17
  botToken: string;
17
18
  openWithCode: boolean;
18
19
  }
19
20
 
20
21
 
21
22
  export default class DiscordGenerator extends Generator {
22
- private answers: Answers;
23
-
24
- constructor(args: string | string[], options: Generator.GeneratorOptions) {
25
- super(args, options);
26
- }
27
-
28
- async prompting(): Promise<void> {
29
- this.logo();
30
- this.answers = await this.prompt([
31
- {
32
- type: 'input',
33
- name: 'botName',
34
- message: 'Your Discord Bot name:',
35
- default: 'my-bot',
36
- validate: (input: string): boolean | string =>
37
- new RegExp("^(?:@[a-z0-9-*~][a-z0-9-*._~]*/)?[a-z0-9-~][a-z0-9-._~]*$").test(input)
38
- ? true
39
- : 'Invalid bot name. Please use only lowercase letters, numbers, and hyphens. Must start with a letter.'
40
- },
41
- {
42
- type: 'list',
43
- name: 'botType',
44
- message: 'The type of Discord Bot you want to create.',
45
- choices: [
46
- {
47
- name: 'New Discord Bot (TypeScript)',
48
- value: 'typescript'
49
- },
50
- {
51
- name: 'New Discord Bot (JavaScript)',
52
- value: 'javascript'
53
- }
54
- ,
55
- {
56
- name: 'New Discord Bot (Python)',
57
- value: 'python'
58
- }
59
- ]
60
- },
61
- {
62
- type: 'input',
63
- name: 'botToken',
64
- message: 'Your Discord Bot Token. (Enter to leave blank)',
65
- default: 'your-bot-token'
66
- }
67
- ]);
68
- }
69
-
70
- logo(): void {
71
- this.log(" \x1b[36m_____ _ _ \x1b[31m_ ");
72
- this.log(" \x1b[36m| __ \\(_) | | \x1b[31m(_) ");
73
- this.log(" \x1b[36m| | | |_ ___ ___ ___ _ __ __| | \x1b[33m_ ___ ");
74
- this.log(" \x1b[36m| | | | / __|/ __/ _ \\| '__/ _` | \x1b[33m| / __|");
75
- this.log(" \x1b[36m| |__| | \\__ \\ (_| (_) | | | (_| |\x1b[37m_\x1b[32m| \\__ \\");
76
- this.log(" \x1b[36m|_____/|_|___/\\___\\___/|_| \\__,_\x1b[37m(_) \x1b[32m|___/");
77
- this.log(" \x1b[34m_/ | ");
78
- this.log(" \x1b[35m|__/ ");
79
- this.log("\x1b[0m");
80
- }
81
-
82
- writing(): void {
83
- this.sourceRoot(path.join(__dirname, TEMPLATE_DIR + this.answers.botType));
84
- ['.'].forEach(
85
- (path: string) => {
86
- const replaceWords = (
87
- answers: Answers,
88
- content: Buffer
89
- ): string =>
90
- [
91
- [BOT_NAME, this.answers.botName],
92
- [BOT_TOKEN, this.answers.botToken]
93
- ].reduce(
94
- (acc: string, [templateWord, userAnswer]) =>
95
- acc.replace(
96
- new RegExp(
97
- `${OPEN}${templateWord}${CLOSE}`,
98
- 'g'
99
- ),
100
- userAnswer
101
- ),
102
- content.toString()
103
- );
104
- this.fs.copy(
105
- this.templatePath(path),
106
- this.destinationPath(
107
- USER_DIR,
108
- this.answers.botName,
109
- path
110
- ),
111
- {
112
- process: (content: Buffer) =>
113
- replaceWords(this.answers, content)
114
- }
115
- );
116
- }
117
- );
118
- }
119
-
120
- async install(): Promise<void> {
121
- this.log('');
122
- if (this.answers.botType === 'typescript' || this.answers.botType === 'javascript') {
123
- const options = { cwd: this.destinationPath(USER_DIR, this.answers.botName) };
124
- this.spawnCommandSync('npm', ['install'], options);
125
- if(this.answers.botType === 'typescript') {
126
- this.spawnCommandSync('npm', ['run', 'build'], options);
127
- }
128
- }
129
-
130
- this.log('Your Discord Bot ' + this.answers.botName + ' has been created!');
131
-
132
- }
133
-
134
- async end(): Promise<void> {
135
- const answer = await this.prompt({
136
- type: 'list',
137
- name: 'openWithCode',
138
- message: 'Do you want to open your Discord Bot with Visual Studio Code?',
139
- choices: [
140
- {
141
- name: 'open with `code`',
142
- value: true
143
- },
144
- {
145
- name: 'skip',
146
- value: false
147
- }
148
- ]
149
- });
150
- this.log('');
151
- if (answer && answer.openWithCode) {
152
- this.spawnCommand('code', [this.destinationPath(
153
- USER_DIR,
154
- this.answers.botName
155
- )]);
156
- }
157
- }
23
+ private answers: Answers = {} as Answers;
24
+
25
+ constructor(args: string | string[], options: Generator.GeneratorOptions) {
26
+ super(args, options);
27
+ }
28
+
29
+ async prompting(): Promise<void> {
30
+ this.logo();
31
+ this.answers = await this.prompt([
32
+ {
33
+ type: 'input',
34
+ name: 'botName',
35
+ message: 'Your Discord Bot name:',
36
+ default: 'my-bot',
37
+ validate: (input: string): boolean | string =>
38
+ new RegExp('^(?:@[a-z0-9-*~][a-z0-9-*._~]*/)?[a-z0-9-~][a-z0-9-._~]*$').test(input)
39
+ ? true
40
+ : 'Invalid bot name. Please use only lowercase letters, numbers, and hyphens. Must start with a letter.'
41
+ },
42
+ {
43
+ type: 'list',
44
+ name: 'botType',
45
+ message: 'The type of Discord Bot you want to create.',
46
+ choices: [
47
+ {
48
+ name: 'New Discord Bot (TypeScript)',
49
+ value: 'typescript'
50
+ },
51
+ {
52
+ name: 'New Discord Bot (JavaScript)',
53
+ value: 'javascript'
54
+ },
55
+ {
56
+ name: 'New Discord Bot (Python)',
57
+ value: 'python'
58
+ },
59
+ {
60
+ name: 'New Discord Bot (Rust)',
61
+ value: 'rust'
62
+ },
63
+ ]
64
+ },
65
+ {
66
+ type: 'input',
67
+ name: 'botToken',
68
+ message: 'Your Discord Bot Token. (Enter to leave blank)',
69
+ default: 'your-bot-token'
70
+ }
71
+ ]);
72
+ }
73
+
74
+ logo(): void {
75
+ this.log(' \x1b[36m_____ _ _ \x1b[31m_ ');
76
+ this.log(' \x1b[36m| __ \\(_) | | \x1b[31m(_) ');
77
+ this.log(' \x1b[36m| | | |_ ___ ___ ___ _ __ __| | \x1b[33m_ ___ ');
78
+ this.log(' \x1b[36m| | | | / __|/ __/ _ \\| \'__/ _` | \x1b[33m| / __|');
79
+ this.log(' \x1b[36m| |__| | \\__ \\ (_| (_) | | | (_| |\x1b[37m_\x1b[32m| \\__ \\');
80
+ this.log(' \x1b[36m|_____/|_|___/\\___\\___/|_| \\__,_\x1b[37m(_) \x1b[32m|___/');
81
+ this.log(' \x1b[34m_/ | ');
82
+ this.log(' \x1b[35m|__/ ');
83
+ this.log('\x1b[0m');
84
+ }
85
+
86
+ writing(): void {
87
+ this.sourceRoot(path.join(__dirname, TEMPLATE_DIR + this.answers.botType));
88
+ ['.'].forEach(
89
+ (path: string) => {
90
+ this.fs.copy(
91
+ this.templatePath(path),
92
+ this.destinationPath(
93
+ USER_DIR,
94
+ this.answers.botName,
95
+ path
96
+ ),
97
+ {
98
+ process: (content: Buffer) => this._replaceWords(content, this.answers)
99
+ }
100
+ );
101
+ }
102
+ );
103
+ }
104
+
105
+ async install(): Promise<void> {
106
+ this.log('');
107
+ if (this.answers.botType === 'typescript' || this.answers.botType === 'javascript') {
108
+ const options = { cwd: this.destinationPath(USER_DIR, this.answers.botName) };
109
+ this.spawnCommandSync('npm', ['install'], options);
110
+ if(this.answers.botType === 'typescript') {
111
+ this.spawnCommandSync('npm', ['run', 'build'], options);
112
+ }
113
+ }
114
+
115
+ this.log('Your Discord Bot ' + this.answers.botName + ' has been created!');
116
+
117
+ }
118
+
119
+ async end(): Promise<void> {
120
+ const answer = await this.prompt({
121
+ type: 'list',
122
+ name: 'openWithCode',
123
+ message: 'Do you want to open your Discord Bot with Visual Studio Code?',
124
+ choices: [
125
+ {
126
+ name: 'open with `code`',
127
+ value: true
128
+ },
129
+ {
130
+ name: 'skip',
131
+ value: false
132
+ }
133
+ ]
134
+ });
135
+ this.log('');
136
+ if (answer && answer.openWithCode) {
137
+ this.spawnCommand('code', [this.destinationPath(
138
+ USER_DIR,
139
+ this.answers.botName
140
+ )]);
141
+ }
142
+ }
143
+
144
+ _replaceWords(content: Buffer, answers: Answers): string {
145
+ if(answers.botType === 'rust') {
146
+ return content.toString()
147
+ .replace(BOT_TOKEN, answers.botToken)
148
+ .replace(BOT_NAME_RUST, answers.botName);
149
+ }
150
+
151
+ return content.toString()
152
+ .replace(BOT_TOKEN,answers.botToken)
153
+ .replace(BOT_NAME, answers.botName);
154
+ }
158
155
  }
@@ -7,32 +7,32 @@ const prefix = '!';
7
7
 
8
8
  // Run this code when the client is ready. This event will only trigger one time after logging in
9
9
  client.once('ready', () => {
10
- console.log(`Bot is logged in as ${client.user.tag}.`);
10
+ console.log(`Bot is logged in as ${client.user.tag}.`);
11
11
  });
12
12
 
13
13
 
14
14
  // Listen for messages
15
15
  client.on('messageCreate', async message => {
16
- // Ignore messages that don't start with the prefix or are from a bot
17
- if (!message.content.startsWith(prefix) || message.author.bot) return;
18
-
19
- // Split the message into command and arguments
20
- const args = message.content.slice(prefix.length).trim().split(/ +/);
21
- const command = args.shift()?.toLowerCase();
22
-
23
- // ping - bot will reply with Pong!
24
- if (command === 'ping') {
25
- await message.reply('Pong!');
26
- }
27
- // say <message> - bot will send the message
28
- else if (command === 'say') {
29
- if (!args.length) {
30
- await message.channel.send(`You didn't provide any arguments, ${message.author}!`);
31
- return;
32
- }
33
- await message.channel.send(args.join(' '));
34
- return;
35
- }
16
+ // Ignore messages that don't start with the prefix or are from a bot
17
+ if (!message.content.startsWith(prefix) || message.author.bot) return;
18
+
19
+ // Split the message into command and arguments
20
+ const args = message.content.slice(prefix.length).trim().split(/ +/);
21
+ const command = args.shift()?.toLowerCase();
22
+
23
+ // ping - bot will reply with Pong!
24
+ if (command === 'ping') {
25
+ await message.reply('Pong!');
26
+ }
27
+ // say <message> - bot will send the message
28
+ else if (command === 'say') {
29
+ if (!args.length) {
30
+ await message.channel.send(`You didn't provide any arguments, ${message.author}!`);
31
+ return;
32
+ }
33
+ await message.channel.send(args.join(' '));
34
+ return;
35
+ }
36
36
  });
37
37
 
38
38
 
@@ -0,0 +1 @@
1
+ discord.py ~= 2.3.2
@@ -0,0 +1,10 @@
1
+ [package]
2
+ name = "bot_name"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+
6
+ # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7
+
8
+ [dependencies]
9
+ serenity = { version = "0.11.6", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] }
10
+ tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }
@@ -0,0 +1,72 @@
1
+ use serenity::async_trait;
2
+ use serenity::model::channel::Message;
3
+ use serenity::model::gateway::Ready;
4
+ use serenity::prelude::*;
5
+
6
+ struct Handler;
7
+
8
+ const PREFIX: &str = "!";
9
+ const TOKEN: &str = "<%= bot-token %>";
10
+
11
+ #[async_trait]
12
+ impl EventHandler for Handler {
13
+
14
+ async fn message(&self, ctx: Context, msg: Message) {
15
+ // check if the message starts with the prefix
16
+ if msg.content.starts_with(&PREFIX) && !msg.author.bot {
17
+
18
+ // Split the message into command and arguments
19
+ let args = msg.content[PREFIX.len()..].trim().split(' ').collect::<Vec<&str>>();
20
+ let command = args[0];
21
+
22
+ // ping - bot will reply with Pong!
23
+ if command == "ping" {
24
+ // send a message to the channel
25
+ if let Err(why) = msg.channel_id.say(&ctx.http, "Pong!").await {
26
+ println!("Error sending message: {:?}", why);
27
+ }
28
+ }
29
+ // say <message> - bot will send the message
30
+ else if command == "say" {
31
+
32
+ // check if the user has provided a message
33
+ if args.len() == 1 {
34
+ if let Err(why) = msg.reply(&ctx.http, "Please provide a message to send.").await {
35
+ println!("Error sending message: {:?}", why);
36
+ }
37
+ return;
38
+ }
39
+
40
+ // send a message to the channel using the rest of the arguments
41
+ if let Err(why) = msg.channel_id.say(&ctx.http, &args[1..].join(" ")).await {
42
+ println!("Error sending message: {:?}", why);
43
+ }
44
+ }
45
+ }
46
+ }
47
+
48
+ async fn ready(&self, _: Context, ready: Ready) {
49
+ println!("Bot is logged in as {}.", ready.user.name);
50
+ }
51
+ }
52
+
53
+ #[tokio::main]
54
+ async fn main() {
55
+
56
+ // Set gateway intents, which decides what events the bot will be notified about
57
+ let intents = GatewayIntents::GUILD_MESSAGES
58
+ | GatewayIntents::DIRECT_MESSAGES
59
+ | GatewayIntents::MESSAGE_CONTENT;
60
+
61
+
62
+ // Create a new instance of the client
63
+ let mut client = Client::builder(&TOKEN, intents).event_handler(Handler).await.expect("Err creating client");
64
+
65
+
66
+ // Start the bot
67
+ if let Err(why) = client.start().await {
68
+ println!("Client error: {:?}", why);
69
+ }
70
+ }
71
+
72
+ // for more information on how to use serenity, check out the docs at https://docs.rs/serenity
@@ -11,6 +11,6 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "discord.js": "^14.13.0",
14
- "typescript": "^5.1.6"
14
+ "typescript": "^5.2.2"
15
15
  }
16
16
  }
@@ -7,32 +7,32 @@ const prefix = '!';
7
7
 
8
8
  // Run this code when the client is ready. This event will only trigger one time after logging in
9
9
  client.once('ready', () => {
10
- console.log(`Bot is logged in as ${client.user.tag}.`);
10
+ console.log(`Bot is logged in as ${client.user!.tag}.`);
11
11
  });
12
12
 
13
13
 
14
14
  // Listen for messages
15
15
  client.on('messageCreate', async message => {
16
- // Ignore messages that don't start with the prefix or are from a bot
17
- if(!message.content.startsWith(prefix) || message.author.bot) return;
16
+ // Ignore messages that don't start with the prefix or are from a bot
17
+ if(!message.content.startsWith(prefix) || message.author.bot) return;
18
18
 
19
- // Split the message into command and arguments
20
- const args = message.content.slice(prefix.length).trim().split(/ +/);
21
- const command = args.shift()?.toLowerCase();
19
+ // Split the message into command and arguments
20
+ const args = message.content.slice(prefix.length).trim().split(/ +/);
21
+ const command = args.shift()?.toLowerCase();
22
22
 
23
- // ping - bot will reply with Pong!
24
- if(command === 'ping') {
25
- await message.reply('Pong!');
26
- }
27
- // say <message> - bot will send the message
28
- else if(command === 'say') {
29
- if(!args.length) {
30
- await message.channel.send(`You didn't provide any arguments, ${message.author}!`);
31
- return;
32
- }
33
- await message.channel.send(args.join(' '));
34
- return;
35
- }
23
+ // ping - bot will reply with Pong!
24
+ if(command === 'ping') {
25
+ await message.reply('Pong!');
26
+ }
27
+ // say <message> - bot will send the message
28
+ else if(command === 'say') {
29
+ if(!args.length) {
30
+ await message.channel.send(`You didn't provide any arguments, ${message.author}!`);
31
+ return;
32
+ }
33
+ await message.channel.send(args.join(' '));
34
+ return;
35
+ }
36
36
  });
37
37
 
38
38
 
@@ -5,7 +5,7 @@
5
5
  "lib": ["ESNext"],
6
6
  "sourceMap": true,
7
7
  "outDir": "dist",
8
- "strict": false,
8
+ "strict": true,
9
9
  "noUnusedLocals": true,
10
10
  "noImplicitReturns": true,
11
11
  "moduleResolution": "node",
@@ -1,54 +1,70 @@
1
1
  import { describe, test } from 'vitest';
2
2
  import path from 'path';
3
3
  import { createHelpers } from 'yeoman-test';
4
- import {EOL} from 'os'
4
+ import {EOL} from 'os';
5
5
 
6
6
  const typescriptAnswers = {
7
- botName: 'typescript-bot',
8
- botType: 'typescript',
9
- botToken: 'xxx',
10
- openWithCode: false,
11
- }
7
+ botName: 'typescript-bot',
8
+ botType: 'typescript',
9
+ botToken: 'xxx',
10
+ openWithCode: false,
11
+ };
12
12
 
13
13
  const pythonAnswers = {
14
- botName: 'python-bot',
15
- botType: 'python',
16
- botToken: 'xxxx',
17
- openWithCode: false,
18
- }
14
+ botName: 'python-bot',
15
+ botType: 'python',
16
+ botToken: 'xxxx',
17
+ openWithCode: false,
18
+ };
19
19
 
20
20
  describe('Check if the generator works', () => {
21
- test('Should generate typescript files', async () => {
22
- const context = createHelpers({}).run(path.join(__dirname, '../app'));
23
- context.targetDirectory = path.join(__dirname, '../test-temp'); // generate in test-temp
24
- context.cleanTestDirectory(true); // clean-up test-temp
25
- await context.onGenerator(generator => generator.destinationRoot(context.targetDirectory, false))
26
- .withAnswers(typescriptAnswers)
27
- .then((result) => {
28
- result.assertFile([`${typescriptAnswers.botName}/package.json`]);
29
- result.assertFile([`${typescriptAnswers.botName}/config.json`]);
30
- result.assertFile([`${typescriptAnswers.botName}/src/index.ts`]);
31
- result.assertFileContent(`${typescriptAnswers.botName}/config.json`, CONFIG_JSON_EXPECTED);
32
- });
33
- context.cleanup(); // clean-up
34
- }, 120_000);
35
- test('Should generate python files', async () => {
36
- const context = createHelpers({}).run(path.join(__dirname, '../app'));
37
- context.targetDirectory = path.join(__dirname, '../test-temp'); // generate in test-temp
38
- context.cleanTestDirectory(true); // clean-up test-temp
39
- await context.onGenerator(generator => generator.destinationRoot(context.targetDirectory, false))
40
- .withAnswers(pythonAnswers)
41
- .then((result) => {
42
- result.assertFile([`${pythonAnswers.botName}/bot.py`]);
43
- result.assertFileContent(`${pythonAnswers.botName}/bot.py`, BOT_PY_EXPECTED);
44
- });
45
- context.cleanup(); // clean-up
46
- }, 120_000);
21
+ test('Should generate typescript files', async () => {
22
+ const context = createHelpers({}).run(path.join(__dirname, '../app'));
23
+ context.targetDirectory = path.join(__dirname, '../test-temp'); // generate in test-temp
24
+ context.cleanTestDirectory(true); // clean-up test-temp
25
+ await context.onGenerator(generator => generator.destinationRoot(context.targetDirectory, false))
26
+ .withAnswers(typescriptAnswers)
27
+ .then((result) => {
28
+ result.assertFile([`${typescriptAnswers.botName}/package.json`]);
29
+ result.assertFile([`${typescriptAnswers.botName}/config.json`]);
30
+ result.assertFile([`${typescriptAnswers.botName}/src/index.ts`]);
31
+ result.assertFileContent(`${typescriptAnswers.botName}/config.json`, CONFIG_JSON_EXPECTED);
32
+ });
33
+ context.cleanup(); // clean-up
34
+ }, 120_000);
35
+ test('Should generate python files', async () => {
36
+ const context = createHelpers({}).run(path.join(__dirname, '../app'));
37
+ context.targetDirectory = path.join(__dirname, '../test-temp'); // generate in test-temp
38
+ context.cleanTestDirectory(true); // clean-up test-temp
39
+ await context.onGenerator(generator => generator.destinationRoot(context.targetDirectory, false))
40
+ .withAnswers(pythonAnswers)
41
+ .then((result) => {
42
+ result.assertFile([`${pythonAnswers.botName}/bot.py`]);
43
+ result.assertFileContent(`${pythonAnswers.botName}/bot.py`, BOT_PY_EXPECTED);
44
+ });
45
+ context.cleanup(); // clean-up
46
+ }, 120_000);
47
+ test('Should generate rust files', async () => {
48
+ const context = createHelpers({}).run(path.join(__dirname, '../app'));
49
+ context.targetDirectory = path.join(__dirname, '../test-temp'); // generate in test-temp
50
+ context.cleanTestDirectory(true); // clean-up test-temp
51
+ await context.onGenerator(generator => generator.destinationRoot(context.targetDirectory, false))
52
+ .withAnswers({
53
+ ...pythonAnswers,
54
+ botType: 'rust',
55
+ })
56
+ .then((result) => {
57
+ result.assertFile([`${pythonAnswers.botName}/Cargo.toml`]);
58
+ result.assertFile([`${pythonAnswers.botName}/src/main.rs`]);
59
+ });
60
+ context.cleanup(); // clean-up
61
+ }
62
+ , 120_000);
47
63
  });
48
64
 
49
65
 
50
66
  function normilizeEOL(str: string) {
51
- return str.replace(/\r?\n/g, EOL);
67
+ return str.replace(/\r?\n/g, EOL);
52
68
  }
53
69
 
54
70
  // norminlize end of line