wikiploy 1.1.0 → 1.2.2

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.
@@ -7,20 +7,20 @@
7
7
  {
8
8
  "type": "node",
9
9
  "request": "launch",
10
- "name": "Run current JS",
10
+ "name": "Deploy test.js",
11
11
  "skipFiles": [
12
12
  "<node_internals>/**"
13
13
  ],
14
- "program": "${workspaceFolder}\\${file}"
14
+ "program": "${workspaceFolder}\\src\\Wiki_bot_test.js"
15
15
  },
16
16
  {
17
17
  "type": "node",
18
18
  "request": "launch",
19
- "name": "Deploy test.js",
19
+ "name": "Run current JS",
20
20
  "skipFiles": [
21
21
  "<node_internals>/**"
22
22
  ],
23
- "program": "${workspaceFolder}\\src\\Wiki_bot_test.js"
23
+ "program": "${workspaceFolder}\\${file}"
24
24
  }
25
25
  ]
26
26
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wikiploy",
3
- "version": "1.1.0",
3
+ "version": "1.2.2",
4
4
  "description": "User scripts and gadgets deployment for MediaWiki (Wikipedia).",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -6,14 +6,37 @@ export default class DeployConfig {
6
6
  * @param {DeployConfig} page Edit page (tab).
7
7
  */
8
8
  constructor(options) {
9
+ /** Source page. */
9
10
  this.src = options?.src;
11
+ /** Destination page. */
10
12
  this.dst = options?.dst;
11
13
  if (!this.dst) {
12
14
  this.dst = `~/${this.src}`;
13
15
  }
16
+ if (this.dst.indexOf('~')===0) {
17
+ this._dst = this.dst;
18
+ }
19
+ /** Wiki site (domain). */
20
+ this.site = options?.site;
21
+ if (!this.site || typeof this.site != 'string') {
22
+ this.site = '';
23
+ }
24
+ }
25
+
26
+ /** Does this config require a user. */
27
+ needsUser() {
28
+ return this._dst ? true : false;
29
+ }
30
+ /** Setup user. */
31
+ setUser(userName) {
32
+ if (this._dst) {
33
+ this.dst = this._dst.replace(/^~/, 'User:' + userName);
34
+ return true;
35
+ }
36
+ return false;
14
37
  }
15
38
 
16
- /** info */
39
+ /** info. */
17
40
  info() {
18
41
  return `deploy "${this.src}" to "${this.dst}"`;
19
42
  }
package/src/WikiOps.js CHANGED
@@ -99,11 +99,27 @@ export default class WikiOps {
99
99
  }
100
100
 
101
101
  /** Go to url (and wait for it). */
102
- async goto(page, url) {
102
+ async goto(page, url, skipDisarm) {
103
103
  let nav = page.waitForNavigation(); // init wait
104
104
  await page.goto(url);
105
105
  await nav; // wait for url
106
- await this.disarmUnloadWarning(page);
106
+ if (!skipDisarm) {
107
+ await this.disarmUnloadWarning(page);
108
+ }
109
+ }
110
+
111
+ /** Read current MW user. */
112
+ async readUser(page) {
113
+ let user = await page.evaluate(() => {
114
+ return mw?.config?.get('wgUserName', '--');
115
+ });
116
+ if (!user) {
117
+ console.warn('problem reading user, too early?');
118
+ }
119
+ if (user === '--') {
120
+ user = false;
121
+ }
122
+ return user;
107
123
  }
108
124
 
109
125
  /** Change intput's value. */
@@ -10,12 +10,22 @@ const ployBot = new Wikiploy();
10
10
  const configs = [];
11
11
  configs.push(new DeployConfig({
12
12
  src: 'assets/test.js',
13
- dst: 'User:Nux/test-jsbot--test.js',
13
+ dst: '~/test-jsbot--test.js',
14
14
  }));
15
15
  configs.push(new DeployConfig({
16
16
  src: 'assets/test.css',
17
- dst: 'User:Nux/test-jsbot--test.css',
17
+ dst: '~/test-jsbot--test.css',
18
18
  }));
19
+ // configs.push(new DeployConfig({
20
+ // src: 'assets/test.js',
21
+ // dst: '~/test-jsbot--test.js',
22
+ // site: 'en.wikipedia.org',
23
+ // }));
24
+ // configs.push(new DeployConfig({
25
+ // src: 'assets/test.css',
26
+ // dst: '~/test-jsbot--test.css',
27
+ // site: 'en.wikipedia.org',
28
+ // }));
19
29
  await ployBot.deploy(configs);
20
30
  })().catch(err => {
21
31
  console.error(err);
package/src/Wikiploy.js CHANGED
@@ -2,6 +2,8 @@ import puppeteer, { Browser } from 'puppeteer'; // v13+
2
2
 
3
3
  import WikiOps from './WikiOps.js';
4
4
  import PageCache from './PageCache.js';
5
+ // eslint-disable-next-line no-unused-vars
6
+ import DeployConfig from './DeployConfig.js';
5
7
 
6
8
  import { promises as fs } from "fs"; // node v11+
7
9
 
@@ -26,12 +28,17 @@ export default class Wikiploy {
26
28
  this.mock = false;
27
29
  /** Wait before close [ms] (or you can set a breakpoint to check stuff). */
28
30
  this.mockSleep = 0;
31
+ /** Default wiki site (domain). */
32
+ this.site = 'pl.wikipedia.org';
29
33
 
30
- /** Browser connection. */
34
+ /** @private Browser connection. */
31
35
  this._browser = false;
32
36
 
33
- /** Bot helper. */
37
+ /** @private Bot helper. */
34
38
  this._bot = new WikiOps(this.cache);
39
+
40
+ /** @private Users cache. */
41
+ this._users = {};
35
42
  }
36
43
 
37
44
  /**
@@ -42,7 +49,7 @@ export default class Wikiploy {
42
49
  const bot = this._bot;
43
50
  const browser = await this.init();
44
51
  const page = await bot.openTab(browser);
45
- console.log(JSON.stringify(configs));
52
+ // console.log(JSON.stringify(configs));
46
53
  // main loop
47
54
  for (const config of configs) {
48
55
  await this.save(config, page);
@@ -60,14 +67,18 @@ export default class Wikiploy {
60
67
  async save(config, page) {
61
68
  console.log('[Wikiploy]', config.info());
62
69
  const bot = this._bot;
70
+ // prepare user
71
+ if (config.needsUser()) {
72
+ await this.prepareUser(config, page);
73
+ }
63
74
  // navigate
64
- let url = this.editUrl(config.dst);
75
+ let url = this.editUrl(config.dst, config);
65
76
  await bot.goto(page, url);
66
77
  // insert the content of the file into the edit field
67
78
  const contents = await fs.readFile(config.src, 'utf8');
68
79
  await bot.fillEdit(page, contents);
69
80
  // edit description
70
- const summary = this.preapreSummary(config);
81
+ const summary = this.prepareSummary(config);
71
82
  await bot.fillSummary(page, summary);
72
83
 
73
84
  // save
@@ -79,27 +90,78 @@ export default class Wikiploy {
79
90
  }
80
91
  }
81
92
 
93
+ /**
94
+ * Prepare user in config.
95
+ *
96
+ * Note! Modifies the config.
97
+ *
98
+ * @param {DeployConfig} config Config.
99
+ * @param {Page} page
100
+ * @private
101
+ */
102
+ async prepareUser(config, page) {
103
+ const bot = this._bot;
104
+
105
+ let site = config.site;
106
+ // from cache
107
+ if (site in this._users) {
108
+ let changed = config.setUser(this._users[site]);
109
+ return changed;
110
+ }
111
+
112
+ // any page
113
+ let url = this.liteUrl(config);
114
+ await bot.goto(page, url, true);
115
+
116
+ // read
117
+ let userName = await bot.readUser(page);
118
+ if (!userName) {
119
+ throw 'Unable to read user name. Not authenticated?';
120
+ }
121
+
122
+ // save to cache
123
+ this._users[site] = userName;
124
+
125
+ // finalize
126
+ let changed = config.setUser(userName);
127
+ return changed;
128
+ }
82
129
 
83
130
  /**
84
131
  * Prepare edit summary.
85
132
  *
86
- * @param {String} pageTitle Title with namespace.
87
- * @returns {String} Full edit URL.
133
+ * @param {DeployConfig} config Config.
134
+ * @returns {String} Edit summary.
135
+ * @private
136
+ */
137
+ prepareSummary(config) {
138
+ return '#Wikiploy' + ` ${config.src}`;
139
+ }
140
+
141
+ /**
142
+ * Prepare base URL.
143
+ *
144
+ * @param {DeployConfig} config Configuration.
145
+ * @returns {String} Base URL.
88
146
  * @private
89
147
  */
90
- preapreSummary(config) {
91
- return '[Wikiploy]' + ` ${config.src}`;
148
+ baseUrl(config) {
149
+ const site = config.site.length ? config.site : this.site;
150
+ const origin = `https://${site}`;
151
+ const baseUrl = `${origin}/w/index.php`;
152
+ return baseUrl;
92
153
  }
93
154
 
94
155
  /**
95
156
  * Prepare edit URL.
96
157
  *
97
158
  * @param {String} pageTitle Title with namespace.
159
+ * @param {DeployConfig} config Configuration.
98
160
  * @returns {String} Full edit URL.
99
161
  * @private
100
162
  */
101
- editUrl(pageTitle) {
102
- const baseUrl = `https://pl.wikipedia.org/w/index.php`; // TODO: config/options
163
+ editUrl(pageTitle, config) {
164
+ const baseUrl = this.baseUrl(config);
103
165
 
104
166
  // common params
105
167
  // note that submit action is not affected by new wikicode editor
@@ -111,6 +173,25 @@ export default class Wikiploy {
111
173
  return baseUrl + '?title=' + encodeURIComponent(pageTitle) + params;
112
174
  }
113
175
 
176
+ /**
177
+ * Prepare URL of some lite page.
178
+ *
179
+ * @param {DeployConfig} config Configuration.
180
+ * @returns {String} URL within Wiki.
181
+ * @private
182
+ */
183
+ liteUrl(config) {
184
+ const baseUrl = this.baseUrl(config);
185
+
186
+ // common params
187
+ // note that submit action is not affected by new wikicode editor
188
+ let params = `
189
+ &useskin=monobook
190
+ `.replace(/\s+/g, '');
191
+
192
+ return baseUrl + '?title=User:Nux/blank.js' + params;
193
+ }
194
+
114
195
  /**
115
196
  * Init browser connection.
116
197
  *
@@ -0,0 +1,78 @@
1
+ /* global describe, it */
2
+ import { assert } from 'chai';
3
+ import DeployConfig from '../src/DeployConfig.js';
4
+
5
+ describe('DeployConfig', function () {
6
+
7
+ describe('init', function () {
8
+ it('should set src, dst', function () {
9
+ let config = {
10
+ src: 'test.src.js',
11
+ dst: 'User:Nux/test.dst.js',
12
+ };
13
+ let result = new DeployConfig(config);
14
+ console.log(result);
15
+ assert.equal(result.src, config.src);
16
+ assert.equal(result.dst, config.dst);
17
+ // console.log(new DeployConfig({
18
+ // src: 'test.js',
19
+ // }));
20
+ });
21
+ it('should default to home', function () {
22
+ let config = {
23
+ src: 'test.js',
24
+ };
25
+ let expected = '~/test.js';
26
+ let result = new DeployConfig(config);
27
+ console.log(result);
28
+ assert.equal(result.dst, expected);
29
+ });
30
+ });
31
+
32
+ describe('setUser', function () {
33
+ it('should set userName', function () {
34
+ let config = {
35
+ src: 'test.js',
36
+ };
37
+ let userName = 'Tester';
38
+ let expected = 'User:Tester/test.js';
39
+ let result = new DeployConfig(config);
40
+ result.setUser(userName);
41
+ console.log(result);
42
+ assert.equal(result.dst, expected);
43
+
44
+
45
+ result = new DeployConfig({
46
+ src: 'assets/test.js',
47
+ dst: '~/test-jsbot--test.js',
48
+ });
49
+ result.setUser(userName);
50
+ console.log(result);
51
+ assert.isTrue(result.dst.indexOf('~') < 0);
52
+ });
53
+ it('should change user', function () {
54
+ let config = {
55
+ src: 'test.js',
56
+ };
57
+ let userName1 = 'Tester1';
58
+ let userName2 = 'Tester2';
59
+ let expected = 'User:Tester2/test.js';
60
+ let result = new DeployConfig(config);
61
+ result.setUser(userName1);
62
+ console.log(result);
63
+ result.setUser(userName2);
64
+ console.log(result);
65
+ assert.equal(result.dst, expected);
66
+ });
67
+ it('should keep inner tilde', function () {
68
+ let config = {
69
+ src: 'test.js',
70
+ dst: 'Mediawiki/~test.js',
71
+ };
72
+ let userName = 'Tester';
73
+ let result = new DeployConfig(config);
74
+ result.setUser(userName);
75
+ assert.equal(result.dst, config.dst);
76
+ });
77
+ });
78
+ });
@@ -1,31 +0,0 @@
1
- /* global describe, it */
2
- import { assert } from 'chai';
3
- import DeployConfig from '../DeployConfig.js';
4
-
5
- describe('DeployConfig', function () {
6
-
7
- describe('init', function () {
8
- it('should set src, dst', function () {
9
- let config = {
10
- src: 'test.src.js',
11
- dst: 'User:Nux/test.dst.js',
12
- };
13
- let result = new DeployConfig(config);
14
- console.log(result);
15
- assert.equal(result.src, config.src);
16
- assert.equal(result.dst, config.dst);
17
- // console.log(new DeployConfig({
18
- // src: 'test.js',
19
- // }));
20
- });
21
- it('should default to home', function () {
22
- let config = {
23
- src: 'test.js',
24
- };
25
- let expected = '~/test.js';
26
- let result = new DeployConfig(config);
27
- console.log(result);
28
- assert.equal(result.dst, expected);
29
- });
30
- });
31
- });