mirror of
https://github.com/syuilo/ai.git
synced 2024-11-24 22:01:07 +00:00
maze
This commit is contained in:
parent
37ef9094a8
commit
7c4ac882ef
173
package-lock.json
generated
173
package-lock.json
generated
|
@ -3,6 +3,11 @@
|
|||
"requires": true,
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"@types/caseless": {
|
||||
"version": "0.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz",
|
||||
"integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w=="
|
||||
},
|
||||
"@types/chalk": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/chalk/-/chalk-2.2.0.tgz",
|
||||
|
@ -16,6 +21,14 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz",
|
||||
"integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA=="
|
||||
},
|
||||
"@types/form-data": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz",
|
||||
"integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==",
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/lokijs": {
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/lokijs/-/lokijs-1.5.2.tgz",
|
||||
|
@ -34,6 +47,30 @@
|
|||
"@types/retry": "*"
|
||||
}
|
||||
},
|
||||
"@types/random-seed": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/random-seed/-/random-seed-0.3.3.tgz",
|
||||
"integrity": "sha512-kHsCbIRHNXJo6EN5W8EA5b4i1hdT6jaZke5crBPLUcLqaLdZ0QBq8QVMbafHzhjFF83Cl9qlee2dChD18d/kPg=="
|
||||
},
|
||||
"@types/request": {
|
||||
"version": "2.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.1.tgz",
|
||||
"integrity": "sha512-ZgEZ1TiD+KGA9LiAAPPJL68Id2UWfeSO62ijSXZjFJArVV+2pKcsVHmrcu+1oiE3q6eDGiFiSolRc4JHoerBBg==",
|
||||
"requires": {
|
||||
"@types/caseless": "*",
|
||||
"@types/form-data": "*",
|
||||
"@types/node": "*",
|
||||
"@types/tough-cookie": "*"
|
||||
}
|
||||
},
|
||||
"@types/request-promise-native": {
|
||||
"version": "1.0.16",
|
||||
"resolved": "https://registry.npmjs.org/@types/request-promise-native/-/request-promise-native-1.0.16.tgz",
|
||||
"integrity": "sha512-gbLf6cg1XGBU8BObOgs5VkCQo5JFz2GstgZjyE4FRbig/jiCEdiynu2fCzJlw3qYPuoj59spKnvuRLN4PsMvhA==",
|
||||
"requires": {
|
||||
"@types/request": "*"
|
||||
}
|
||||
},
|
||||
"@types/retry": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
|
||||
|
@ -44,6 +81,16 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.28.tgz",
|
||||
"integrity": "sha512-SMA+fUwULwK7sd/ZJicUztiPs8F1yCPwF3O23Z9uQ32ME5Ha0NmDK9+QTsYE4O2tHXChzXomSWWeIhCnoN1LqA=="
|
||||
},
|
||||
"@types/tmp": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.1.0.tgz",
|
||||
"integrity": "sha512-6IwZ9HzWbCq6XoQWhxLpDjuADodH/MKXRUIDFudvgjcVdjFknvmR+DNsoUeer4XPrEnrZs04Jj+kfV9pFsrhmA=="
|
||||
},
|
||||
"@types/tough-cookie": {
|
||||
"version": "2.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.5.tgz",
|
||||
"integrity": "sha512-SCcK7mvGi3+ZNz833RRjFIxrn4gI1PPR3NtuIS+6vMkvmsGjosqTJwRt5bAEFLRz+wtJMWv8+uOnZf2hi2QXTg=="
|
||||
},
|
||||
"@types/uuid": {
|
||||
"version": "3.4.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.4.tgz",
|
||||
|
@ -138,6 +185,11 @@
|
|||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
|
||||
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||
},
|
||||
"bcrypt-pbkdf": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
|
@ -146,6 +198,15 @@
|
|||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"buffer-from": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
|
||||
|
@ -187,6 +248,11 @@
|
|||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
|
@ -264,6 +330,11 @@
|
|||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||
},
|
||||
"getpass": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||
|
@ -272,6 +343,19 @@
|
|||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.4",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
|
||||
"integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
|
@ -301,6 +385,20 @@
|
|||
"sshpk": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
},
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
|
@ -311,6 +409,11 @@
|
|||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
|
||||
},
|
||||
"jpeg-js": {
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.3.5.tgz",
|
||||
"integrity": "sha512-hvaExqwmQDS8O9qnZAVDXGWU43Tbu1V0wMZmjROjT11jloSgGICZpscG+P6Nyi1BVAvyu2ARRx8qmEW30sxgdQ=="
|
||||
},
|
||||
"jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
|
@ -383,6 +486,14 @@
|
|||
"mime-db": "~1.38.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"misskey-reversi": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/misskey-reversi/-/misskey-reversi-0.0.5.tgz",
|
||||
|
@ -393,11 +504,34 @@
|
|||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"opentype.js": {
|
||||
"version": "0.4.11",
|
||||
"resolved": "https://registry.npmjs.org/opentype.js/-/opentype.js-0.4.11.tgz",
|
||||
"integrity": "sha1-KBojkGOcwVkxyVXY1jwUp8d3K0E="
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||
},
|
||||
"pngjs": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz",
|
||||
"integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w=="
|
||||
},
|
||||
"promise-retry": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz",
|
||||
|
@ -417,11 +551,29 @@
|
|||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||
},
|
||||
"pureimage": {
|
||||
"version": "0.1.6",
|
||||
"resolved": "https://registry.npmjs.org/pureimage/-/pureimage-0.1.6.tgz",
|
||||
"integrity": "sha512-t74leLaXyD3VGmMbcFZNWZoHqPQNX805gHYNBCrNEVRjUkDfdlopLJnDJI9QYdhWXwtNiD02coq+NB7+CryAwg==",
|
||||
"requires": {
|
||||
"jpeg-js": "^0.3.3",
|
||||
"opentype.js": "^0.4.3",
|
||||
"pngjs": "^3.3.1"
|
||||
}
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
||||
},
|
||||
"random-seed": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/random-seed/-/random-seed-0.3.0.tgz",
|
||||
"integrity": "sha1-2UXy4fOPSejViRNDG4v2u5N1Vs0=",
|
||||
"requires": {
|
||||
"json-stringify-safe": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"reconnecting-websocket": {
|
||||
"version": "4.1.10",
|
||||
"resolved": "https://registry.npmjs.org/reconnecting-websocket/-/reconnecting-websocket-4.1.10.tgz",
|
||||
|
@ -477,6 +629,14 @@
|
|||
"resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz",
|
||||
"integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q="
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.6.3",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
|
||||
"integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
|
@ -551,6 +711,14 @@
|
|||
"resolved": "https://registry.npmjs.org/timeout-as-promise/-/timeout-as-promise-1.0.0.tgz",
|
||||
"integrity": "sha1-c2foEfyZKs/Nzaq/LlDfr4shV28="
|
||||
},
|
||||
"tmp": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz",
|
||||
"integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==",
|
||||
"requires": {
|
||||
"rimraf": "^2.6.3"
|
||||
}
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
|
||||
|
@ -620,6 +788,11 @@
|
|||
"extsprintf": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
},
|
||||
"ws": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
|
||||
|
|
|
@ -10,7 +10,10 @@
|
|||
"@types/lokijs": "1.5.2",
|
||||
"@types/node": "10.0.5",
|
||||
"@types/promise-retry": "1.1.3",
|
||||
"@types/random-seed": "0.3.3",
|
||||
"@types/request-promise-native": "1.0.16",
|
||||
"@types/seedrandom": "2.4.28",
|
||||
"@types/tmp": "0.1.0",
|
||||
"@types/uuid": "3.4.4",
|
||||
"@types/ws": "6.0.1",
|
||||
"autobind-decorator": "2.4.0",
|
||||
|
@ -19,11 +22,14 @@
|
|||
"mecab-async": "0.1.2",
|
||||
"misskey-reversi": "0.0.5",
|
||||
"promise-retry": "1.1.1",
|
||||
"pureimage": "0.1.6",
|
||||
"random-seed": "0.3.0",
|
||||
"reconnecting-websocket": "4.1.10",
|
||||
"request": "2.88.0",
|
||||
"request-promise-native": "1.0.7",
|
||||
"seedrandom": "2.4.3",
|
||||
"timeout-as-promise": "1.0.0",
|
||||
"tmp": "0.1.0",
|
||||
"ts-node": "8.0.3",
|
||||
"typescript": "2.8.3",
|
||||
"uuid": "3.3.2",
|
||||
|
|
22
src/ai.ts
22
src/ai.ts
|
@ -1,5 +1,6 @@
|
|||
// AI CORE
|
||||
|
||||
import * as fs from 'fs';
|
||||
import autobind from 'autobind-decorator';
|
||||
import * as loki from 'lokijs';
|
||||
import * as request from 'request-promise-native';
|
||||
|
@ -59,6 +60,7 @@ export default class 藍 {
|
|||
}>;
|
||||
|
||||
public friends: loki.Collection<FriendDoc>;
|
||||
public moduleData: loki.Collection<any>;
|
||||
|
||||
/**
|
||||
* 藍インスタンスを生成します
|
||||
|
@ -105,6 +107,10 @@ export default class 藍 {
|
|||
this.friends = this.getCollection('friends', {
|
||||
indices: ['userId']
|
||||
});
|
||||
|
||||
this.moduleData = this.getCollection('moduleData', {
|
||||
indices: ['module']
|
||||
});
|
||||
//#endregion
|
||||
|
||||
// Init stream
|
||||
|
@ -281,6 +287,22 @@ export default class 藍 {
|
|||
return friend;
|
||||
}
|
||||
|
||||
/**
|
||||
* ファイルをドライブにアップロードします
|
||||
*/
|
||||
@autobind
|
||||
public async upload(readStream: fs.ReadStream) {
|
||||
const res = await request.post({
|
||||
url: `${config.apiUrl}/drive/files/create`,
|
||||
formData: {
|
||||
i: config.i,
|
||||
file: readStream
|
||||
},
|
||||
json: true
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 投稿します
|
||||
*/
|
||||
|
|
|
@ -19,6 +19,7 @@ import DiceModule from './modules/dice';
|
|||
import ServerModule from './modules/server';
|
||||
import FollowModule from './modules/follow';
|
||||
import ValentineModule from './modules/valentine';
|
||||
import MazeModule from './modules/maze';
|
||||
|
||||
import chalk from 'chalk';
|
||||
import * as request from 'request-promise-native';
|
||||
|
@ -69,6 +70,7 @@ promiseRetry(retry => {
|
|||
new BirthdayModule(),
|
||||
new ValentineModule(),
|
||||
new KeywordModule(),
|
||||
new MazeModule(),
|
||||
]);
|
||||
}).catch(e => {
|
||||
log(chalk.red('Failed to fetch the account'));
|
||||
|
|
|
@ -5,9 +5,21 @@ export default abstract class Module {
|
|||
public abstract readonly name: string;
|
||||
|
||||
protected ai: 藍;
|
||||
private doc: any;
|
||||
|
||||
public init(ai: 藍) {
|
||||
this.ai = ai;
|
||||
|
||||
this.doc = this.ai.moduleData.findOne({
|
||||
module: this.name
|
||||
});
|
||||
|
||||
if (this.doc == null) {
|
||||
this.doc = this.ai.moduleData.insertOne({
|
||||
module: this.name,
|
||||
data: {}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public abstract install(): InstallerResult;
|
||||
|
@ -48,4 +60,15 @@ export default abstract class Module {
|
|||
public setTimeoutWithPersistence(delay: number, data?: any) {
|
||||
this.ai.setTimeoutWithPersistence(this, delay, data);
|
||||
}
|
||||
|
||||
@autobind
|
||||
protected getData() {
|
||||
return this.doc.data;
|
||||
}
|
||||
|
||||
@autobind
|
||||
protected setData(data: any) {
|
||||
this.doc.data = data;
|
||||
this.ai.moduleData.update(this.doc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ export const itemPrefixes = [
|
|||
'Microsoft製',
|
||||
'Apple製',
|
||||
'人類の技術を結集して作った',
|
||||
'2018年製',
|
||||
'2018年製', // TODO ランダム
|
||||
'500kgくらいある',
|
||||
'高級',
|
||||
'腐った',
|
||||
|
|
472
src/modules/maze/index.ts
Normal file
472
src/modules/maze/index.ts
Normal file
|
@ -0,0 +1,472 @@
|
|||
/**
|
||||
* Random avatar generator
|
||||
*/
|
||||
|
||||
const p = require('pureimage');
|
||||
import * as gen from 'random-seed';
|
||||
import * as fs from 'fs';
|
||||
import autobind from 'autobind-decorator';
|
||||
import Module from '../../module';
|
||||
import serifs from '../../serifs';
|
||||
import * as tmp from 'tmp';
|
||||
|
||||
type CellType = 'empty' | 'left' | 'right' | 'top' | 'bottom' | 'leftTop' | 'leftBottom' | 'rightTop' | 'rightBottom' | 'leftRightTop' | 'leftRightBottom' | 'leftTopBottom' | 'rightTopBottom' | 'leftRight' | 'topBottom' | 'cross';
|
||||
|
||||
type Dir = 'left' | 'right' | 'top' | 'bottom';
|
||||
|
||||
const cellVariants = {
|
||||
empty: {
|
||||
digg: { left: 'left', right: 'right', top: 'top', bottom: 'bottom' },
|
||||
cross: { left: false, right: false, top: false, bottom: false },
|
||||
},
|
||||
left: {
|
||||
digg: { left: null, right: 'leftRight', top: 'leftTop', bottom: 'leftBottom' },
|
||||
cross: { left: false, right: false, top: false, bottom: false },
|
||||
},
|
||||
right: {
|
||||
digg: { left: 'leftRight', right: null, top: 'rightTop', bottom: 'rightBottom' },
|
||||
cross: { left: false, right: false, top: false, bottom: false },
|
||||
},
|
||||
top: {
|
||||
digg: { left: 'leftTop', right: 'rightTop', top: null, bottom: 'topBottom' },
|
||||
cross: { left: false, right: false, top: false, bottom: false },
|
||||
},
|
||||
bottom: {
|
||||
digg: { left: 'leftBottom', right: 'rightBottom', top: 'topBottom', bottom: null },
|
||||
cross: { left: false, right: false, top: false, bottom: false },
|
||||
},
|
||||
leftTop: {
|
||||
digg: { left: null, right: 'leftRightTop', top: null, bottom: 'leftTopBottom' },
|
||||
cross: { left: false, right: false, top: false, bottom: false },
|
||||
},
|
||||
leftBottom: {
|
||||
digg: { left: null, right: 'leftRightBottom', top: 'leftTopBottom', bottom: null },
|
||||
cross: { left: false, right: false, top: false, bottom: false },
|
||||
},
|
||||
rightTop: {
|
||||
digg: { left: 'leftRightTop', right: null, top: null, bottom: 'rightTopBottom' },
|
||||
cross: { left: false, right: false, top: false, bottom: false },
|
||||
},
|
||||
rightBottom: {
|
||||
digg: { left: 'leftRightBottom', right: null, top: 'rightTopBottom', bottom: null },
|
||||
cross: { left: false, right: false, top: false, bottom: false },
|
||||
},
|
||||
leftRightTop: {
|
||||
digg: { left: null, right: null, top: null, bottom: null },
|
||||
cross: { left: false, right: false, top: false, bottom: false },
|
||||
},
|
||||
leftRightBottom: {
|
||||
digg: { left: null, right: null, top: null, bottom: null },
|
||||
cross: { left: false, right: false, top: false, bottom: false },
|
||||
},
|
||||
leftTopBottom: {
|
||||
digg: { left: null, right: null, top: null, bottom: null },
|
||||
cross: { left: false, right: false, top: false, bottom: false },
|
||||
},
|
||||
rightTopBottom: {
|
||||
digg: { left: null, right: null, top: null, bottom: null },
|
||||
cross: { left: false, right: false, top: false, bottom: false },
|
||||
},
|
||||
leftRight: {
|
||||
digg: { left: null, right: null, top: 'leftRightTop', bottom: 'leftRightBottom' },
|
||||
cross: { left: false, right: false, top: true, bottom: true },
|
||||
},
|
||||
topBottom: {
|
||||
digg: { left: 'leftTopBottom', right: 'rightTopBottom', top: null, bottom: null },
|
||||
cross: { left: true, right: true, top: false, bottom: false },
|
||||
},
|
||||
cross: {
|
||||
digg: { left: 'cross', right: 'cross', top: 'cross', bottom: 'cross' },
|
||||
cross: { left: false, right: false, top: false, bottom: false },
|
||||
},
|
||||
} as { [k in CellType]: {
|
||||
digg: { left: CellType | null; right: CellType | null; top: CellType | null; bottom: CellType | null; };
|
||||
cross: { left: boolean; right: boolean; top: boolean; bottom: boolean; };
|
||||
} };
|
||||
|
||||
const imageSize = 2048; // px
|
||||
const margin = 256;
|
||||
const mazeAreaSize = imageSize - (margin * 2);
|
||||
|
||||
const themes = [{
|
||||
bg1: '#C1D9CE',
|
||||
bg2: '#F2EDD5',
|
||||
wall: '#0F8AA6',
|
||||
road: '#C1D9CE',
|
||||
marker: '#84BFBF',
|
||||
}, {
|
||||
bg1: '#17275B',
|
||||
bg2: '#1F2E67',
|
||||
wall: '#17275B',
|
||||
road: '#6A77A4',
|
||||
marker: '#E6E5E3',
|
||||
}, {
|
||||
bg1: '#194035',
|
||||
bg2: '#417334',
|
||||
wall: '#594020',
|
||||
road: '#A67926',
|
||||
marker: '#2E4D59',
|
||||
}];
|
||||
|
||||
export default class extends Module {
|
||||
public readonly name = 'maze';
|
||||
|
||||
@autobind
|
||||
public install() {
|
||||
this.post();
|
||||
setInterval(this.post, 1000 * 60 * 3);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
@autobind
|
||||
private async post() {
|
||||
const now = new Date();
|
||||
if (now.getHours() !== 11) return;
|
||||
const date = `${now.getFullYear()}-${now.getMonth()}-${now.getDate()}`;
|
||||
const data = this.getData();
|
||||
if (data.lastPosted == date) return;
|
||||
data.lastPosted = date;
|
||||
this.setData(data);
|
||||
|
||||
const seed = date;
|
||||
|
||||
this.log('Maze generating...');
|
||||
const maze = this.genMize(seed);
|
||||
|
||||
this.log('Maze rendering...');
|
||||
const [temp] = await this.createTemp();
|
||||
await this.renderMaze(seed, maze, fs.createWriteStream(temp));
|
||||
|
||||
this.log('Image uploading...');
|
||||
const file = await this.ai.upload(fs.createReadStream(temp));
|
||||
|
||||
this.log('Posting...');
|
||||
this.ai.post({
|
||||
text: serifs.maze.post,
|
||||
fileIds: [file.id]
|
||||
});
|
||||
}
|
||||
|
||||
@autobind
|
||||
private createTemp(): Promise<[string, any]> {
|
||||
return new Promise<[string, any]>((res, rej) => {
|
||||
tmp.file((e, path, fd, cleanup) => {
|
||||
if (e) return rej(e);
|
||||
res([path, cleanup]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@autobind
|
||||
private genMize(seed) {
|
||||
const rand = gen.create(seed);
|
||||
|
||||
const mazeSize = 10 + rand(21);
|
||||
|
||||
// maze (filled by 'empty')
|
||||
const maze: CellType[][] = new Array(mazeSize);
|
||||
for (let i = 0; i < mazeSize; i++) {
|
||||
maze[i] = new Array(mazeSize).fill('empty');
|
||||
}
|
||||
|
||||
const origin = {
|
||||
x: rand(mazeSize),
|
||||
y: rand(mazeSize),
|
||||
};
|
||||
|
||||
function checkDiggable(x: number, y: number, dir: Dir) {
|
||||
if (cellVariants[maze[x][y]].digg[dir] === null) return false;
|
||||
|
||||
const newPos =
|
||||
dir === 'top' ? { x: x, y: y - 1 } :
|
||||
dir === 'bottom' ? { x: x, y: y + 1 } :
|
||||
dir === 'left' ? { x: x - 1, y: y } :
|
||||
dir === 'right' ? { x: x + 1, y: y } :
|
||||
{ x, y };
|
||||
|
||||
if (newPos.x < 0 || newPos.y < 0 || newPos.x >= mazeSize || newPos.y >= mazeSize) return false;
|
||||
|
||||
const cell = maze[newPos.x][newPos.y];
|
||||
if (cell === 'empty') return true;
|
||||
if (cellVariants[cell].cross[dir] && checkDiggable(newPos.x, newPos.y, dir)) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function diggFrom(x: number, y: number) {
|
||||
const isUpDiggable = checkDiggable(x, y, 'top');
|
||||
const isRightDiggable = checkDiggable(x, y, 'right');
|
||||
const isDownDiggable = checkDiggable(x, y, 'bottom');
|
||||
const isLeftDiggable = checkDiggable(x, y, 'left');
|
||||
|
||||
if (!isUpDiggable && !isRightDiggable && !isDownDiggable && !isLeftDiggable) return;
|
||||
|
||||
const dirs: Dir[] = [];
|
||||
if (isUpDiggable) dirs.push('top');
|
||||
if (isRightDiggable) dirs.push('right');
|
||||
if (isDownDiggable) dirs.push('bottom');
|
||||
if (isLeftDiggable) dirs.push('left');
|
||||
|
||||
const dir = dirs[rand(dirs.length)];
|
||||
|
||||
maze[x][y] = cellVariants[maze[x][y]].digg[dir];
|
||||
|
||||
if (dir === 'top') {
|
||||
maze[x][y - 1] = maze[x][y - 1] === 'empty' ? 'bottom' : 'cross';
|
||||
diggFrom(x, y - 1);
|
||||
return;
|
||||
}
|
||||
if (dir === 'right') {
|
||||
maze[x + 1][y] = maze[x + 1][y] === 'empty' ? 'left' : 'cross';
|
||||
diggFrom(x + 1, y);
|
||||
return;
|
||||
}
|
||||
if (dir === 'bottom') {
|
||||
maze[x][y + 1] = maze[x][y + 1] === 'empty' ? 'top' : 'cross';
|
||||
diggFrom(x, y + 1);
|
||||
return;
|
||||
}
|
||||
if (dir === 'left') {
|
||||
maze[x - 1][y] = maze[x - 1][y] === 'empty' ? 'right' : 'cross';
|
||||
diggFrom(x - 1, y);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
diggFrom(origin.x, origin.y);
|
||||
|
||||
let hasEmptyCell = true;
|
||||
while (hasEmptyCell) {
|
||||
const nonEmptyCells = [];
|
||||
|
||||
for (let y = 0; y < mazeSize; y++) {
|
||||
for (let x = 0; x < mazeSize; x++) {
|
||||
const cell = maze[x][y];
|
||||
if (cell !== 'empty' && cell !== 'cross') nonEmptyCells.push([x, y]);
|
||||
}
|
||||
}
|
||||
|
||||
const pos = nonEmptyCells[rand(nonEmptyCells.length)];
|
||||
|
||||
diggFrom(pos[0], pos[1]);
|
||||
|
||||
hasEmptyCell = false;
|
||||
for (let y = 0; y < mazeSize; y++) {
|
||||
for (let x = 0; x < mazeSize; x++) {
|
||||
if (maze[x][y] === 'empty') hasEmptyCell = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return maze;
|
||||
}
|
||||
|
||||
@autobind
|
||||
private renderMaze(seed, maze: CellType[][], stream: fs.WriteStream): Promise<void> {
|
||||
const rand = gen.create(seed);
|
||||
const mazeSize = maze.length;
|
||||
|
||||
const colors = themes[rand(themes.length)];
|
||||
|
||||
const canvas = p.make(imageSize, imageSize);
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
ctx.fillStyle = colors.bg1;
|
||||
ctx.beginPath();
|
||||
ctx.fillRect(0, 0, imageSize, imageSize);
|
||||
|
||||
ctx.fillStyle = colors.bg2;
|
||||
ctx.beginPath();
|
||||
ctx.fillRect(margin / 2, margin / 2, imageSize - ((margin / 2) * 2), imageSize - ((margin / 2) * 2));
|
||||
|
||||
// Draw
|
||||
function drawCell(ctx, x, y, size, left, right, top, bottom, mark) {
|
||||
const wallThickness = size / 8;
|
||||
const wallMargin = size / 4;
|
||||
const markerMargin = size / 3;
|
||||
|
||||
ctx.fillStyle = colors.road;
|
||||
if (left) {
|
||||
ctx.beginPath();
|
||||
ctx.fillRect(x, y + wallMargin, size - wallMargin, size - (wallMargin * 2));
|
||||
}
|
||||
if (right) {
|
||||
ctx.beginPath();
|
||||
ctx.fillRect(x + wallMargin, y + wallMargin, size - wallMargin, size - (wallMargin * 2));
|
||||
}
|
||||
if (top) {
|
||||
ctx.beginPath();
|
||||
ctx.fillRect(x + wallMargin, y, size - (wallMargin * 2), size - wallMargin);
|
||||
}
|
||||
if (bottom) {
|
||||
ctx.beginPath();
|
||||
ctx.fillRect(x + wallMargin, y + wallMargin, size - (wallMargin * 2), size - wallMargin);
|
||||
}
|
||||
|
||||
if (mark) {
|
||||
ctx.fillStyle = colors.marker;
|
||||
ctx.beginPath();
|
||||
ctx.fillRect(x + markerMargin, y + markerMargin, size - (markerMargin * 2), size - (markerMargin * 2));
|
||||
}
|
||||
|
||||
const wallLeftTopX = x + wallMargin - (wallThickness / 2);
|
||||
const wallLeftTopY = y + wallMargin - (wallThickness / 2);
|
||||
const wallRightTopX = x + size - wallMargin - (wallThickness / 2);
|
||||
const wallRightTopY = y + wallMargin - (wallThickness / 2);
|
||||
const wallLeftBottomX = x + wallMargin - (wallThickness / 2);
|
||||
const wallLeftBottomY = y + size - wallMargin - (wallThickness / 2);
|
||||
const wallRightBottomX = x + size - wallMargin - (wallThickness / 2);
|
||||
const wallRightBottomY = y + size - wallMargin - (wallThickness / 2);
|
||||
|
||||
ctx.fillStyle = colors.wall;
|
||||
if (left && right && top && bottom) {
|
||||
ctx.beginPath();
|
||||
if (rand(2) === 0) {
|
||||
ctx.fillRect(x + wallMargin - (wallThickness / 2), y, wallThickness, size);
|
||||
ctx.fillRect(x + size - wallMargin - (wallThickness / 2), y, wallThickness, size);
|
||||
ctx.fillRect(x, y + wallMargin - (wallThickness / 2), wallMargin, wallThickness);
|
||||
ctx.fillRect(x + size - wallMargin, y + wallMargin - (wallThickness / 2), wallMargin, wallThickness);
|
||||
ctx.fillRect(x, y + size - wallMargin - (wallThickness / 2), wallMargin, wallThickness);
|
||||
ctx.fillRect(x + size - wallMargin, y + size - wallMargin - (wallThickness / 2), wallMargin, wallThickness);
|
||||
} else {
|
||||
ctx.fillRect(x, y + wallMargin - (wallThickness / 2), size, wallThickness);
|
||||
ctx.fillRect(x, y + size - wallMargin - (wallThickness / 2), size, wallThickness);
|
||||
ctx.fillRect(wallLeftTopX, y, wallThickness, wallMargin - (wallThickness / 2));
|
||||
ctx.fillRect(wallRightTopX, y, wallThickness, wallMargin - (wallThickness / 2));
|
||||
ctx.fillRect(wallLeftTopX, wallLeftBottomY, wallThickness, wallMargin + (wallThickness / 2));
|
||||
ctx.fillRect(wallRightTopX, wallRightBottomY, wallThickness, wallMargin + (wallThickness / 2));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!left && right && !top && bottom) {
|
||||
ctx.beginPath();
|
||||
ctx.fillRect(wallLeftTopX, wallLeftTopY, size - wallMargin + (wallThickness / 2), wallThickness);
|
||||
ctx.fillRect(wallLeftTopX, wallLeftTopY, wallThickness, size - wallMargin + (wallThickness / 2));
|
||||
}
|
||||
|
||||
if (right && bottom) {
|
||||
ctx.fillRect(wallRightBottomX, wallRightBottomY, wallMargin + (wallThickness / 2), wallThickness);
|
||||
ctx.fillRect(wallRightBottomX, wallRightBottomY, wallThickness, wallMargin + (wallThickness / 2));
|
||||
}
|
||||
|
||||
if (left && !right && !top && bottom) {
|
||||
ctx.beginPath();
|
||||
ctx.fillRect(x, y + wallMargin - (wallThickness / 2), size - wallMargin + (wallThickness / 2), wallThickness);
|
||||
ctx.fillRect(wallRightTopX, y + wallMargin - (wallThickness / 2), wallThickness, size - wallMargin + (wallThickness / 2));
|
||||
}
|
||||
|
||||
if (left && bottom) {
|
||||
ctx.fillRect(x, wallLeftBottomY, wallMargin - (wallThickness / 2), wallThickness);
|
||||
ctx.fillRect(wallLeftBottomX, wallLeftBottomY, wallThickness, wallMargin + (wallThickness / 2));
|
||||
}
|
||||
|
||||
if (!left && right && top && !bottom) {
|
||||
ctx.beginPath();
|
||||
ctx.fillRect(wallLeftBottomX, y, wallThickness, size - wallMargin + (wallThickness / 2));
|
||||
ctx.fillRect(wallLeftBottomX, wallLeftBottomY, size - wallMargin + (wallThickness / 2), wallThickness);
|
||||
}
|
||||
|
||||
if (right && top) {
|
||||
ctx.fillRect(wallRightTopX, y, wallThickness, wallMargin - (wallThickness / 2));
|
||||
ctx.fillRect(wallRightTopX, wallRightTopY, size - wallMargin - (wallThickness * 2), wallThickness);
|
||||
}
|
||||
|
||||
if (left && !right && top && !bottom) {
|
||||
ctx.beginPath();
|
||||
ctx.fillRect(x, wallLeftBottomY, size - wallMargin - (wallThickness / 2), wallThickness);
|
||||
ctx.fillRect(wallRightTopX, y, wallThickness, size - wallMargin + (wallThickness / 2));
|
||||
}
|
||||
|
||||
if (left && top) {
|
||||
ctx.fillRect(wallLeftTopX, y, wallThickness, wallMargin + (wallThickness / 2));
|
||||
ctx.fillRect(x, wallLeftTopY, wallMargin - (wallThickness / 2), wallThickness);
|
||||
}
|
||||
|
||||
if (!left && right && !top && !bottom) {
|
||||
ctx.beginPath();
|
||||
ctx.fillRect(wallLeftTopX, wallLeftTopY, size - wallMargin + (wallThickness / 2), wallThickness);
|
||||
ctx.fillRect(wallLeftBottomX, wallLeftBottomY, size - wallMargin + (wallThickness / 2), wallThickness);
|
||||
ctx.fillRect(wallLeftTopX, wallLeftTopY, wallThickness, size - wallMargin - (wallThickness * 2));
|
||||
return;
|
||||
}
|
||||
|
||||
if (left && !right && !top && !bottom) {
|
||||
ctx.beginPath();
|
||||
ctx.fillRect(x, wallLeftTopY, size - wallMargin + (wallThickness / 2), wallThickness);
|
||||
ctx.fillRect(x, wallLeftBottomY, size - wallMargin + (wallThickness / 2), wallThickness);
|
||||
ctx.fillRect(wallRightTopX, wallRightTopY, wallThickness, size - wallMargin - (wallThickness * 2));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!left && !right && !top && bottom) {
|
||||
ctx.beginPath();
|
||||
ctx.fillRect(wallLeftTopX, wallLeftTopY, wallThickness, size - wallMargin + (wallThickness / 2));
|
||||
ctx.fillRect(wallRightTopX, wallRightTopY, wallThickness, size - wallMargin + (wallThickness / 2));
|
||||
ctx.fillRect(wallLeftTopX, wallLeftTopY, size - wallMargin - (wallThickness * 2), wallThickness);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!left && !right && top && !bottom) {
|
||||
ctx.beginPath();
|
||||
ctx.fillRect(wallLeftTopX, y, wallThickness, size - wallMargin + (wallThickness / 2));
|
||||
ctx.fillRect(wallRightTopX, y, wallThickness, size - wallMargin + (wallThickness / 2));
|
||||
ctx.fillRect(wallLeftBottomX, wallLeftBottomY, size - wallMargin - (wallThickness * 2), wallThickness);
|
||||
return;
|
||||
}
|
||||
|
||||
if (top && bottom) {
|
||||
if (!left) {
|
||||
ctx.beginPath();
|
||||
ctx.fillRect(x + wallMargin - (wallThickness / 2), y, wallThickness, size);
|
||||
}
|
||||
if (!right) {
|
||||
ctx.beginPath();
|
||||
ctx.fillRect(x + size - wallMargin - (wallThickness / 2), y, wallThickness, size);
|
||||
}
|
||||
}
|
||||
if (left && right) {
|
||||
if (!top) {
|
||||
ctx.beginPath();
|
||||
ctx.fillRect(x, y + wallMargin - (wallThickness / 2), size, wallThickness);
|
||||
}
|
||||
if (!bottom) {
|
||||
ctx.beginPath();
|
||||
ctx.fillRect(x, y + size - wallMargin - (wallThickness / 2), size, wallThickness);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const cellSize = mazeAreaSize / mazeSize;
|
||||
|
||||
for (let x = 0; x < mazeSize; x++) {
|
||||
for (let y = 0; y < mazeSize; y++) {
|
||||
const actualX = margin + (cellSize * x);
|
||||
const actualY = margin + (cellSize * y);
|
||||
|
||||
const cell = maze[x][y];
|
||||
|
||||
const mark = (x === 0 && y === 0) || (x === mazeSize - 1 && y === mazeSize - 1);
|
||||
|
||||
if (cell === 'left') drawCell(ctx, actualX, actualY, cellSize, true, false, false, false, mark);
|
||||
if (cell === 'right') drawCell(ctx, actualX, actualY, cellSize, false, true, false, false, mark);
|
||||
if (cell === 'top') drawCell(ctx, actualX, actualY, cellSize, false, false, true, false, mark);
|
||||
if (cell === 'bottom') drawCell(ctx, actualX, actualY, cellSize, false, false, false, true, mark);
|
||||
if (cell === 'leftTop') drawCell(ctx, actualX, actualY, cellSize, true, false, true, false, mark);
|
||||
if (cell === 'leftBottom') drawCell(ctx, actualX, actualY, cellSize, true, false, false, true, mark);
|
||||
if (cell === 'rightTop') drawCell(ctx, actualX, actualY, cellSize, false, true, true, false, mark);
|
||||
if (cell === 'rightBottom') drawCell(ctx, actualX, actualY, cellSize, false, true, false, true, mark);
|
||||
if (cell === 'leftRightTop') drawCell(ctx, actualX, actualY, cellSize, true, true, true, false, mark);
|
||||
if (cell === 'leftRightBottom') drawCell(ctx, actualX, actualY, cellSize, true, true, false, true, mark);
|
||||
if (cell === 'leftTopBottom') drawCell(ctx, actualX, actualY, cellSize, true, false, true, true, mark);
|
||||
if (cell === 'rightTopBottom') drawCell(ctx, actualX, actualY, cellSize, false, true, true, true, mark);
|
||||
if (cell === 'leftRight') drawCell(ctx, actualX, actualY, cellSize, true, true, false, false, mark);
|
||||
if (cell === 'topBottom') drawCell(ctx, actualX, actualY, cellSize, false, false, true, true, mark);
|
||||
if (cell === 'cross') drawCell(ctx, actualX, actualY, cellSize, true, true, true, true, mark);
|
||||
}
|
||||
}
|
||||
|
||||
return p.encodePNGToStream(canvas, stream);
|
||||
}
|
||||
}
|
|
@ -311,6 +311,10 @@ export default {
|
|||
server: {
|
||||
cpu: 'サーバーの負荷が高そうです。大丈夫でしょうか...?'
|
||||
},
|
||||
|
||||
maze: {
|
||||
post: 'この回路、解読してみてください! #AiMaze'
|
||||
},
|
||||
};
|
||||
|
||||
export function getSerif(variant: string | string[]): string {
|
||||
|
|
Loading…
Reference in a new issue