Add task for building upgrade
This commit is contained in:
parent
5c69dd6a90
commit
b525ff0e27
45
package-lock.json
generated
45
package-lock.json
generated
@ -330,6 +330,15 @@
|
|||||||
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
|
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/jquery": {
|
||||||
|
"version": "3.3.34",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.3.34.tgz",
|
||||||
|
"integrity": "sha512-lW9vsVL53Xu/Nj4gi2hNmHGc4u3KKghjqTkAlO0kF5GIOPxbqqnQpgqJBzmn3yXLrPqHb6cmNJ6URnS23Vtvbg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/sizzle": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/mocha": {
|
"@types/mocha": {
|
||||||
"version": "7.0.2",
|
"version": "7.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz",
|
||||||
@ -342,12 +351,24 @@
|
|||||||
"integrity": "sha512-uzaaDXey/NI2l7kU+xCgWu852Dh/zmf6ZKApc0YQEQpY4DaiZFmLN29E6SLHJfSedj3iNWAndSwfSBpEDadJfg==",
|
"integrity": "sha512-uzaaDXey/NI2l7kU+xCgWu852Dh/zmf6ZKApc0YQEQpY4DaiZFmLN29E6SLHJfSedj3iNWAndSwfSBpEDadJfg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/sizzle": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/url-parse": {
|
"@types/url-parse": {
|
||||||
"version": "1.4.3",
|
"version": "1.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/url-parse/-/url-parse-1.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/url-parse/-/url-parse-1.4.3.tgz",
|
||||||
"integrity": "sha512-4kHAkbV/OfW2kb5BLVUuUMoumB3CP8rHqlw48aHvFy5tf9ER0AfOonBlX29l/DD68G70DmyhRlSYfQPSYpC5Vw==",
|
"integrity": "sha512-4kHAkbV/OfW2kb5BLVUuUMoumB3CP8rHqlw48aHvFy5tf9ER0AfOonBlX29l/DD68G70DmyhRlSYfQPSYpC5Vw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/uuid": {
|
||||||
|
"version": "7.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-7.0.2.tgz",
|
||||||
|
"integrity": "sha512-8Ly3zIPTnT0/8RCU6Kg/G3uTICf9sRwYOpUzSIM3503tLIKcnJPRuinHhXngJUy2MntrEf6dlpOHXJju90Qh5w==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@webassemblyjs/ast": {
|
"@webassemblyjs/ast": {
|
||||||
"version": "1.9.0",
|
"version": "1.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
|
||||||
@ -3262,6 +3283,12 @@
|
|||||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"uuid": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"which": {
|
"which": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||||
@ -3360,6 +3387,12 @@
|
|||||||
"istanbul-lib-report": "^3.0.0"
|
"istanbul-lib-report": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"jquery": {
|
||||||
|
"version": "3.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz",
|
||||||
|
"integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"js-tokens": {
|
"js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
@ -4243,6 +4276,12 @@
|
|||||||
"ansi-regex": "^5.0.0"
|
"ansi-regex": "^5.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"uuid": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"wrap-ansi": {
|
"wrap-ansi": {
|
||||||
"version": "6.2.0",
|
"version": "6.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
|
||||||
@ -5833,9 +5872,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"uuid": {
|
"uuid": {
|
||||||
"version": "3.4.0",
|
"version": "7.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.2.tgz",
|
||||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
"integrity": "sha512-vy9V/+pKG+5ZTYKf+VcphF5Oc6EFiu3W8Nv3P3zIh0EqVI80ZxOzuPfe9EHjkFNvf8+xuTHVeei4Drydlx4zjw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"v8-compile-cache": {
|
"v8-compile-cache": {
|
||||||
|
@ -22,10 +22,13 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/chai": "^4.2.11",
|
"@types/chai": "^4.2.11",
|
||||||
|
"@types/jquery": "^3.3.34",
|
||||||
"@types/mocha": "^7.0.2",
|
"@types/mocha": "^7.0.2",
|
||||||
"@types/node": "^13.9.4",
|
"@types/node": "^13.9.4",
|
||||||
"@types/url-parse": "^1.4.3",
|
"@types/url-parse": "^1.4.3",
|
||||||
|
"@types/uuid": "^7.0.2",
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.2.0",
|
||||||
|
"jquery": "^3.4.1",
|
||||||
"mocha": "^7.1.1",
|
"mocha": "^7.1.1",
|
||||||
"mocha-junit-reporter": "^1.23.3",
|
"mocha-junit-reporter": "^1.23.3",
|
||||||
"nyc": "^15.0.0",
|
"nyc": "^15.0.0",
|
||||||
@ -34,6 +37,7 @@
|
|||||||
"ts-node": "^8.8.1",
|
"ts-node": "^8.8.1",
|
||||||
"typescript": "^3.8.3",
|
"typescript": "^3.8.3",
|
||||||
"url-parse": "^1.4.7",
|
"url-parse": "^1.4.7",
|
||||||
|
"uuid": "^7.0.2",
|
||||||
"webpack": "^4.42.1",
|
"webpack": "^4.42.1",
|
||||||
"webpack-cli": "^3.3.11"
|
"webpack-cli": "^3.3.11"
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
export default abstract class Action {
|
export default abstract class Action {
|
||||||
abstract async run();
|
abstract async run(args);
|
||||||
}
|
}
|
||||||
|
10
src/Action/GoToBuildingAction.ts
Normal file
10
src/Action/GoToBuildingAction.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import Action from './Action';
|
||||||
|
|
||||||
|
export default class GoToBuildingAction extends Action {
|
||||||
|
static NAME = 'go_to_building';
|
||||||
|
|
||||||
|
async run(args): Promise<any> {
|
||||||
|
window.location.assign('/build.php?id=' + args.id);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
17
src/Action/UpgradeBuildingAction.ts
Normal file
17
src/Action/UpgradeBuildingAction.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import Action from './Action';
|
||||||
|
|
||||||
|
export default class UpgradeBuildingAction extends Action {
|
||||||
|
static NAME = 'upgrade_building';
|
||||||
|
|
||||||
|
async run(args): Promise<any> {
|
||||||
|
const btn = jQuery(
|
||||||
|
'.upgradeButtonsContainer .section1 button.green.build'
|
||||||
|
);
|
||||||
|
if (btn.length === 1) {
|
||||||
|
btn.trigger('click');
|
||||||
|
} else {
|
||||||
|
console.log('NO UPGRADE BUTTON');
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
40
src/Dashboard.ts
Normal file
40
src/Dashboard.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import * as URLParse from 'url-parse';
|
||||||
|
import { sleep } from './utils';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
import { QueueItem } from './Queue';
|
||||||
|
import Scheduler from './Scheduler';
|
||||||
|
import UpgradeBuildingTask from './Task/UpgradeBuildingTask';
|
||||||
|
|
||||||
|
export default class Dashboard {
|
||||||
|
private scheduler: Scheduler;
|
||||||
|
|
||||||
|
constructor(scheduler: Scheduler) {
|
||||||
|
this.scheduler = scheduler;
|
||||||
|
}
|
||||||
|
|
||||||
|
async run() {
|
||||||
|
jQuery('body').append(
|
||||||
|
'<div style="position: absolute; top: 0; left: 0; background-color: white">Dashboard</div>'
|
||||||
|
);
|
||||||
|
|
||||||
|
const p = new URLParse(window.location.href, true);
|
||||||
|
console.log('PARSED LOCATION', p);
|
||||||
|
|
||||||
|
await sleep(5000);
|
||||||
|
|
||||||
|
if (p.pathname === '/build.php') {
|
||||||
|
console.log('BUILD PAGE DETECTED');
|
||||||
|
const id = uuid();
|
||||||
|
jQuery('.upgradeButtonsContainer .section1').append(
|
||||||
|
`<div style="padding: 8px"><a id="${id}" href="#">В очередь</a></div>`
|
||||||
|
);
|
||||||
|
jQuery(`#${id}`).on('click', () => {
|
||||||
|
const queueItem = new QueueItem(UpgradeBuildingTask.NAME, {
|
||||||
|
id: p.query['id'],
|
||||||
|
});
|
||||||
|
this.scheduler.pushTask(queueItem);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -27,7 +27,7 @@ export class Queue {
|
|||||||
}
|
}
|
||||||
const first = items.shift();
|
const first = items.shift();
|
||||||
|
|
||||||
localStorage.setItem(this.name, JSON.stringify(items));
|
this.flush(items);
|
||||||
|
|
||||||
if (first === undefined) {
|
if (first === undefined) {
|
||||||
return null;
|
return null;
|
||||||
@ -41,7 +41,12 @@ export class Queue {
|
|||||||
const items = serialized
|
const items = serialized
|
||||||
? (JSON.parse(serialized) as Array<QueueItem>)
|
? (JSON.parse(serialized) as Array<QueueItem>)
|
||||||
: [];
|
: [];
|
||||||
const first = items.push(item);
|
items.push(item);
|
||||||
|
this.flush(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
private flush(items) {
|
||||||
|
console.log('SET NEW QUEUE', this.name, items);
|
||||||
localStorage.setItem(this.name, JSON.stringify(items));
|
localStorage.setItem(this.name, JSON.stringify(items));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { sleep } from './utils';
|
import { sleepLong } from './utils';
|
||||||
import { Queue } from './Queue';
|
import { Queue, QueueItem } from './Queue';
|
||||||
import GoToMainAction from './Action/GoToMainAction';
|
import UpgradeBuildingTask from './Task/UpgradeBuildingTask';
|
||||||
|
import GoToBuildingAction from './Action/GoToBuildingAction';
|
||||||
|
import UpgradeBuildingAction from './Action/UpgradeBuildingAction';
|
||||||
|
|
||||||
const ACTION_QUEUE = 'action_queue';
|
const ACTION_QUEUE = 'action_queue';
|
||||||
const TASK_QUEUE = 'task_queue';
|
const TASK_QUEUE = 'task_queue';
|
||||||
@ -16,39 +18,76 @@ export default class Scheduler {
|
|||||||
|
|
||||||
async run() {
|
async run() {
|
||||||
while (true) {
|
while (true) {
|
||||||
const action = this.popAction();
|
await sleepLong();
|
||||||
console.log('POP ACTION', action);
|
const actionItem = this.popAction();
|
||||||
if (action !== null) {
|
this.log('POP ACTION ITEM', actionItem);
|
||||||
await action.run();
|
if (actionItem !== null) {
|
||||||
|
const action = this.createAction(actionItem);
|
||||||
|
this.log('POP ACTION', action);
|
||||||
|
if (action) {
|
||||||
|
await action.run(actionItem.args);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const task = this.popTask();
|
const taskItem = this.popTask();
|
||||||
console.log('POP TASK', task);
|
this.log('POP TASK ITEM', taskItem);
|
||||||
if (task !== null) {
|
if (taskItem !== null) {
|
||||||
// do task
|
const task = this.createTask(taskItem);
|
||||||
|
this.log('POP TASK', task);
|
||||||
|
if (task !== null) {
|
||||||
|
task.run(taskItem.args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const waitTime = Math.random() * 5000;
|
|
||||||
console.log('WAIT', waitTime);
|
|
||||||
await sleep(waitTime);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pushTask(task: QueueItem): void {
|
||||||
|
this.log('PUSH TASK', task);
|
||||||
|
this.taskQueue.push(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
pushAction(action: QueueItem): void {
|
||||||
|
this.log('PUSH ACTION', action);
|
||||||
|
this.actionQueue.push(action);
|
||||||
|
}
|
||||||
|
|
||||||
private popTask() {
|
private popTask() {
|
||||||
const item = this.taskQueue.pop();
|
const taskItem = this.taskQueue.pop();
|
||||||
if (item === null) {
|
if (taskItem === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
return taskItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private createTask(taskItem: QueueItem) {
|
||||||
|
switch (taskItem.name) {
|
||||||
|
case UpgradeBuildingTask.NAME:
|
||||||
|
return new UpgradeBuildingTask(this);
|
||||||
|
}
|
||||||
|
this.log('UNKNOWN TASK', taskItem.name);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private popAction() {
|
private popAction() {
|
||||||
const item = this.actionQueue.pop();
|
const actionItem = this.actionQueue.pop();
|
||||||
if (item === null) {
|
if (actionItem === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (item.name === 'go_to_main') {
|
this.log('UNKNOWN ACTION', actionItem.name);
|
||||||
return new GoToMainAction();
|
return actionItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private createAction(actionItem: QueueItem) {
|
||||||
|
if (actionItem.name === GoToBuildingAction.NAME) {
|
||||||
|
return new GoToBuildingAction();
|
||||||
|
}
|
||||||
|
if (actionItem.name === UpgradeBuildingAction.NAME) {
|
||||||
|
return new UpgradeBuildingAction();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private log(...args) {
|
||||||
|
console.log('SCHEDULER', ...args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
21
src/Task/UpgradeBuildingTask.ts
Normal file
21
src/Task/UpgradeBuildingTask.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import Scheduler from '../Scheduler';
|
||||||
|
import GoToBuildingAction from '../Action/GoToBuildingAction';
|
||||||
|
import UpgradeBuildingAction from '../Action/UpgradeBuildingAction';
|
||||||
|
import { QueueItem } from '../Queue';
|
||||||
|
|
||||||
|
export default class UpgradeBuildingTask {
|
||||||
|
static NAME = 'upgrade_building';
|
||||||
|
private scheduler: Scheduler;
|
||||||
|
|
||||||
|
constructor(scheduler: Scheduler) {
|
||||||
|
this.scheduler = scheduler;
|
||||||
|
}
|
||||||
|
|
||||||
|
run(args) {
|
||||||
|
console.log('RUN', UpgradeBuildingTask.NAME, 'with', args);
|
||||||
|
this.scheduler.pushAction(new QueueItem(GoToBuildingAction.NAME, args));
|
||||||
|
this.scheduler.pushAction(
|
||||||
|
new QueueItem(UpgradeBuildingAction.NAME, args)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import ModeDetector from './ModeDetector';
|
import ModeDetector from './ModeDetector';
|
||||||
import Scheduler from './Scheduler';
|
import Scheduler from './Scheduler';
|
||||||
|
import Dashboard from './Dashboard';
|
||||||
|
|
||||||
const md = new ModeDetector();
|
const md = new ModeDetector();
|
||||||
if (md.isAuto()) {
|
if (md.isAuto()) {
|
||||||
@ -9,4 +10,6 @@ if (md.isAuto()) {
|
|||||||
scheduler.run();
|
scheduler.run();
|
||||||
} else {
|
} else {
|
||||||
console.log('NORMAL MODE');
|
console.log('NORMAL MODE');
|
||||||
|
const dashboard = new Dashboard(new Scheduler());
|
||||||
|
dashboard.run();
|
||||||
}
|
}
|
||||||
|
14
src/utils.ts
14
src/utils.ts
@ -1,5 +1,15 @@
|
|||||||
function sleep(ms: number) {
|
export function sleep(ms: number) {
|
||||||
return new Promise(resolve => setTimeout(resolve, ms));
|
return new Promise(resolve => setTimeout(resolve, ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
export { sleep };
|
export async function sleepShort() {
|
||||||
|
let ms = 2000 + Math.random() * 10000;
|
||||||
|
console.log('SLEEp SHORT', Math.round(ms));
|
||||||
|
return await sleep(ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function sleepLong() {
|
||||||
|
let ms = 10000 + Math.random() * 10000;
|
||||||
|
console.log('SLEEP LONG', Math.round(ms));
|
||||||
|
return await sleep(ms);
|
||||||
|
}
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
// ==UserScript==
|
|
||||||
// @name New Userscript
|
|
||||||
// @namespace http://tampermonkey.net/
|
|
||||||
// @version 0.1
|
|
||||||
// @description try to take over the world!
|
|
||||||
// @author You
|
|
||||||
// @match http://*/*
|
|
||||||
// @grant none
|
|
||||||
// ==/UserScript==
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// Your code here...
|
|
||||||
})();
|
|
@ -6,7 +6,7 @@
|
|||||||
"target": "es5",
|
"target": "es5",
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"strictNullChecks": true,
|
"strictNullChecks": true,
|
||||||
"types": ["node", "url-parse", "mocha", "chai"]
|
"types": ["node", "url-parse", "jquery", "uuid", "mocha", "chai"]
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"./src/**/*"
|
"./src/**/*"
|
||||||
|
Loading…
Reference in New Issue
Block a user