mirror of
https://github.com/hotomoe/hotomoe
synced 2024-11-24 23:26:17 +09:00
wip
This commit is contained in:
parent
a766faeae9
commit
80e5645a84
@ -6,15 +6,14 @@ import * as fs from 'fs';
|
||||
import * as yaml from 'js-yaml';
|
||||
|
||||
export type LangKey = 'de' | 'en' | 'fr' | 'ja' | 'pl';
|
||||
export type LocaleObjectChildren = LocaleObject | string | undefined;
|
||||
export type LocaleObject = {[key: string]: LocaleObjectChildren };
|
||||
export type LocaleObject = { [key: string]: any };
|
||||
|
||||
const loadLang = (lang: LangKey) => yaml.safeLoad(
|
||||
fs.readFileSync(`./locales/${lang}.yml`, 'utf-8')) as LocaleObject;
|
||||
|
||||
const native = loadLang('ja');
|
||||
|
||||
const langs: {[key in LangKey]: LocaleObject} = {
|
||||
const langs: { [key: string]: LocaleObject } = {
|
||||
'de': loadLang('de'),
|
||||
'en': loadLang('en'),
|
||||
'fr': loadLang('fr'),
|
||||
|
@ -1,4 +1,4 @@
|
||||
export default acct => {
|
||||
export default (acct: string) => {
|
||||
const splitted = acct.split('@', 2);
|
||||
return { username: splitted[0], host: splitted[1] || null };
|
||||
};
|
||||
|
@ -1,3 +1,5 @@
|
||||
export default user => {
|
||||
import { IUser } from "../models/user";
|
||||
|
||||
export default (user: IUser) => {
|
||||
return user.host === null ? user.username : `${user.username}@${user.host}`;
|
||||
};
|
||||
|
@ -2,7 +2,7 @@
|
||||
* Replace i18n texts
|
||||
*/
|
||||
|
||||
import locale, { isAvailableLanguage, LocaleObject, LocaleObjectChildren } from '../../locales';
|
||||
import locale, { isAvailableLanguage, LocaleObject } from '../../locales';
|
||||
|
||||
export default class Replacer {
|
||||
private lang: string;
|
||||
@ -24,7 +24,7 @@ export default class Replacer {
|
||||
|
||||
const texts = locale[this.lang];
|
||||
|
||||
let text: LocaleObjectChildren = texts;
|
||||
let text = texts;
|
||||
|
||||
if (path) {
|
||||
if (text.hasOwnProperty(path)) {
|
||||
|
@ -1,8 +1,8 @@
|
||||
import * as mongo from 'mongodb';
|
||||
import { Query } from 'cafy';
|
||||
|
||||
export const isAnId = x => mongo.ObjectID.isValid(x);
|
||||
export const isNotAnId = x => !isAnId(x);
|
||||
export const isAnId = (x: any) => mongo.ObjectID.isValid(x);
|
||||
export const isNotAnId = (x: any) => !isAnId(x);
|
||||
|
||||
/**
|
||||
* ID
|
||||
|
@ -1,60 +0,0 @@
|
||||
import Note from '../models/note';
|
||||
|
||||
// 10分
|
||||
const interval = 1000 * 60 * 10;
|
||||
|
||||
async function tick() {
|
||||
const res = await Note.aggregate([{
|
||||
$match: {
|
||||
createdAt: {
|
||||
$gt: new Date(Date.now() - interval)
|
||||
},
|
||||
tags: {
|
||||
$exists: true,
|
||||
$ne: []
|
||||
}
|
||||
}
|
||||
}, {
|
||||
$unwind: '$tags'
|
||||
}, {
|
||||
$group: {
|
||||
_id: '$tags',
|
||||
count: {
|
||||
$sum: 1
|
||||
}
|
||||
}
|
||||
}, {
|
||||
$group: {
|
||||
_id: null,
|
||||
tags: {
|
||||
$push: {
|
||||
tag: '$_id',
|
||||
count: '$count'
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
$project: {
|
||||
_id: false,
|
||||
tags: true
|
||||
}
|
||||
}]) as {
|
||||
tags: Array<{
|
||||
tag: string;
|
||||
count: number;
|
||||
}>
|
||||
};
|
||||
|
||||
const stats = res.tags
|
||||
.sort((a, b) => a.count - b.count)
|
||||
.map(tag => [tag.tag, tag.count])
|
||||
.slice(0, 10);
|
||||
|
||||
console.log(stats);
|
||||
|
||||
process.send(stats);
|
||||
}
|
||||
|
||||
tick();
|
||||
|
||||
setInterval(tick, interval);
|
@ -1,20 +0,0 @@
|
||||
import * as childProcess from 'child_process';
|
||||
import Xev from 'xev';
|
||||
|
||||
const ev = new Xev();
|
||||
|
||||
export default function() {
|
||||
const log = [];
|
||||
|
||||
const p = childProcess.fork(__dirname + '/hashtags-stats-child.js');
|
||||
|
||||
p.on('message', stats => {
|
||||
ev.emit('hashtagsStats', stats);
|
||||
log.push(stats);
|
||||
if (log.length > 30) log.shift();
|
||||
});
|
||||
|
||||
ev.on('requestHashTagsStatsLog', id => {
|
||||
ev.emit('hashtagsStatsLog:' + id, log);
|
||||
});
|
||||
}
|
@ -4,7 +4,7 @@ import Xev from 'xev';
|
||||
const ev = new Xev();
|
||||
|
||||
export default function() {
|
||||
const log = [];
|
||||
const log: any[] = [];
|
||||
|
||||
const p = childProcess.fork(__dirname + '/notes-stats-child.js');
|
||||
|
||||
|
@ -11,14 +11,14 @@ const interval = 1000;
|
||||
* Report server stats regularly
|
||||
*/
|
||||
export default function() {
|
||||
const log = [];
|
||||
const log: any[] = [];
|
||||
|
||||
ev.on('requestServerStatsLog', id => {
|
||||
ev.emit('serverStatsLog:' + id, log);
|
||||
});
|
||||
|
||||
async function tick() {
|
||||
osUtils.cpuUsage(cpuUsage => {
|
||||
osUtils.cpuUsage((cpuUsage: number) => {
|
||||
const disk = diskusage.checkSync(os.platform() == 'win32' ? 'c:' : '/');
|
||||
const stats = {
|
||||
cpu_usage: cpuUsage,
|
||||
|
@ -27,7 +27,7 @@ const nativeDbConn = async (): Promise<mongodb.Db> => {
|
||||
if (mdb) return mdb;
|
||||
|
||||
const db = await ((): Promise<mongodb.Db> => new Promise((resolve, reject) => {
|
||||
(mongodb as any).MongoClient.connect(uri, (e, client) => {
|
||||
(mongodb as any).MongoClient.connect(uri, (e: Error, client: any) => {
|
||||
if (e) return reject(e);
|
||||
resolve(client.db(config.mongodb.db));
|
||||
});
|
||||
|
@ -60,7 +60,7 @@ function main() {
|
||||
/**
|
||||
* Init master process
|
||||
*/
|
||||
async function masterMain(opt) {
|
||||
async function masterMain(opt: any) {
|
||||
let config: Config;
|
||||
|
||||
try {
|
||||
@ -91,7 +91,7 @@ async function masterMain(opt) {
|
||||
/**
|
||||
* Init worker process
|
||||
*/
|
||||
async function workerMain(opt) {
|
||||
async function workerMain(opt: any) {
|
||||
if (!opt['only-processor']) {
|
||||
// start server
|
||||
await require('./server').default();
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as mongo from 'mongodb';
|
||||
import * as deepcopy from 'deepcopy';
|
||||
const deepcopy = require('deepcopy');
|
||||
import AccessToken from './access-token';
|
||||
import db from '../db/mongodb';
|
||||
import config from '../config';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as mongo from 'mongodb';
|
||||
import * as deepcopy from 'deepcopy';
|
||||
const deepcopy = require('deepcopy');
|
||||
import db from '../db/mongodb';
|
||||
import { pack as packApp } from './app';
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as mongo from 'mongodb';
|
||||
import * as deepcopy from 'deepcopy';
|
||||
const deepcopy = require('deepcopy');
|
||||
import { pack as packFolder } from './drive-folder';
|
||||
import config from '../config';
|
||||
import monkDb, { nativeDbConn } from '../db/mongodb';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as mongo from 'mongodb';
|
||||
import * as deepcopy from 'deepcopy';
|
||||
const deepcopy = require('deepcopy');
|
||||
import db from '../db/mongodb';
|
||||
import DriveFile from './drive-file';
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as mongo from 'mongodb';
|
||||
import * as deepcopy from 'deepcopy';
|
||||
const deepcopy = require('deepcopy');
|
||||
import db from '../db/mongodb';
|
||||
import { pack as packNote } from './note';
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as mongo from 'mongodb';
|
||||
import * as deepcopy from 'deepcopy';
|
||||
const deepcopy = require('deepcopy');
|
||||
import db from '../db/mongodb';
|
||||
import { pack as packUser } from './user';
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as mongo from 'mongodb';
|
||||
import * as deepcopy from 'deepcopy';
|
||||
const deepcopy = require('deepcopy');
|
||||
import { pack as packUser } from './user';
|
||||
import { pack as packFile } from './drive-file';
|
||||
import db from '../db/mongodb';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as mongo from 'mongodb';
|
||||
import $ from 'cafy';
|
||||
import * as deepcopy from 'deepcopy';
|
||||
const deepcopy = require('deepcopy');
|
||||
import db from '../db/mongodb';
|
||||
import Reaction from './note-reaction';
|
||||
import { pack as packUser } from './user';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as mongo from 'mongodb';
|
||||
import * as deepcopy from 'deepcopy';
|
||||
const deepcopy = require('deepcopy');
|
||||
import rap from '@prezzemolo/rap';
|
||||
import db from '../db/mongodb';
|
||||
import { IUser, pack as packUser } from './user';
|
||||
@ -37,7 +37,11 @@ export type INote = {
|
||||
mediaIds: mongo.ObjectID[];
|
||||
replyId: mongo.ObjectID;
|
||||
renoteId: mongo.ObjectID;
|
||||
poll: any; // todo
|
||||
poll: {
|
||||
choices: Array<{
|
||||
id: number;
|
||||
}>
|
||||
};
|
||||
text: string;
|
||||
tags: string[];
|
||||
tagsLower: string[];
|
||||
@ -304,7 +308,7 @@ export const pack = async (
|
||||
|
||||
if (vote != null) {
|
||||
const myChoice = poll.choices
|
||||
.filter(c => c.id == vote.choice)[0];
|
||||
.filter((c: any) => c.id == vote.choice)[0];
|
||||
|
||||
myChoice.isVoted = true;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as mongo from 'mongodb';
|
||||
import * as deepcopy from 'deepcopy';
|
||||
const deepcopy = require('deepcopy');
|
||||
import db from '../db/mongodb';
|
||||
import { IUser, pack as packUser } from './user';
|
||||
import { pack as packNote } from './note';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as mongo from 'mongodb';
|
||||
import * as deepcopy from 'deepcopy';
|
||||
const deepcopy = require('deepcopy');
|
||||
import db from '../db/mongodb';
|
||||
import { IUser, pack as packUser } from './user';
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as mongo from 'mongodb';
|
||||
import * as deepcopy from 'deepcopy';
|
||||
const deepcopy = require('deepcopy');
|
||||
import db from '../db/mongodb';
|
||||
import { IUser, pack as packUser } from './user';
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as mongo from 'mongodb';
|
||||
import * as deepcopy from 'deepcopy';
|
||||
const deepcopy = require('deepcopy');
|
||||
import db from '../db/mongodb';
|
||||
|
||||
const Signin = db.get<ISignin>('signin');
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as mongo from 'mongodb';
|
||||
import * as deepcopy from 'deepcopy';
|
||||
const deepcopy = require('deepcopy');
|
||||
import db from '../db/mongodb';
|
||||
|
||||
const UserList = db.get<IUserList>('userList');
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as mongo from 'mongodb';
|
||||
import * as deepcopy from 'deepcopy';
|
||||
const deepcopy = require('deepcopy');
|
||||
import sequential = require('promise-sequential');
|
||||
import rap from '@prezzemolo/rap';
|
||||
import db from '../db/mongodb';
|
||||
@ -153,14 +153,6 @@ export function isValidBirthday(birthday: string): boolean {
|
||||
}
|
||||
//#endregion
|
||||
|
||||
export function init(user): IUser {
|
||||
user._id = new mongo.ObjectID(user._id);
|
||||
user.avatarId = new mongo.ObjectID(user.avatarId);
|
||||
user.bannerId = new mongo.ObjectID(user.bannerId);
|
||||
user.pinnedNoteId = new mongo.ObjectID(user.pinnedNoteId);
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Userを物理削除します
|
||||
*/
|
||||
|
@ -1,4 +1,4 @@
|
||||
export default (id, totalItems, orderedItems) => ({
|
||||
export default (id: string, totalItems: any, orderedItems: any) => ({
|
||||
id,
|
||||
type: 'OrderedCollection',
|
||||
totalItems,
|
||||
|
@ -1,4 +1,4 @@
|
||||
export default object => ({
|
||||
export default (object: any) => ({
|
||||
type: 'Reject',
|
||||
object
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { request } from 'https';
|
||||
import { sign } from 'http-signature';
|
||||
const { sign } = require('http-signature');
|
||||
import { URL } from 'url';
|
||||
import * as debug from 'debug';
|
||||
|
||||
@ -8,7 +8,7 @@ import { ILocalUser } from '../../models/user';
|
||||
|
||||
const log = debug('misskey:activitypub:deliver');
|
||||
|
||||
export default (user: ILocalUser, url: string, object) => new Promise((resolve, reject) => {
|
||||
export default (user: ILocalUser, url: string, object: any) => new Promise((resolve, reject) => {
|
||||
log(`--> ${url}`);
|
||||
|
||||
const { protocol, hostname, port, pathname, search } = new URL(url);
|
||||
|
@ -12,8 +12,8 @@ type IWebFinger = {
|
||||
subject: string;
|
||||
};
|
||||
|
||||
export default async function resolve(query): Promise<IWebFinger> {
|
||||
return await new Promise((res, rej) => webFinger.lookup(query, (error, result) => {
|
||||
export default async function resolve(query: any): Promise<IWebFinger> {
|
||||
return await new Promise((res, rej) => webFinger.lookup(query, (error: Error, result: any) => {
|
||||
if (error) {
|
||||
return rej(error);
|
||||
}
|
||||
|
@ -1,377 +0,0 @@
|
||||
/**
|
||||
* -AI-
|
||||
* Botのバックエンド(思考を担当)
|
||||
*
|
||||
* 対話と思考を同じプロセスで行うと、思考時間が長引いたときにストリームから
|
||||
* 切断されてしまうので、別々のプロセスで行うようにします
|
||||
*/
|
||||
|
||||
import * as request from 'request-promise-native';
|
||||
import Reversi, { Color } from '../core';
|
||||
import conf from '../../config';
|
||||
import getUserName from '../../renderers/get-user-name';
|
||||
|
||||
let game;
|
||||
let form;
|
||||
|
||||
/**
|
||||
* BotアカウントのユーザーID
|
||||
*/
|
||||
const id = conf.reversi_ai.id;
|
||||
|
||||
/**
|
||||
* BotアカウントのAPIキー
|
||||
*/
|
||||
const i = conf.reversi_ai.i;
|
||||
|
||||
let note;
|
||||
|
||||
process.on('message', async msg => {
|
||||
// 親プロセスからデータをもらう
|
||||
if (msg.type == '_init_') {
|
||||
game = msg.game;
|
||||
form = msg.form;
|
||||
}
|
||||
|
||||
// フォームが更新されたとき
|
||||
if (msg.type == 'update-form') {
|
||||
form.find(i => i.id == msg.body.id).value = msg.body.value;
|
||||
}
|
||||
|
||||
// ゲームが始まったとき
|
||||
if (msg.type == 'started') {
|
||||
onGameStarted(msg.body);
|
||||
|
||||
//#region TLに投稿する
|
||||
const game = msg.body;
|
||||
const url = `${conf.url}/reversi/${game.id}`;
|
||||
const user = game.user1Id == id ? game.user2 : game.user1;
|
||||
const isSettai = form[0].value === 0;
|
||||
const text = isSettai
|
||||
? `?[${getUserName(user)}](${conf.url}/@${user.username})さんの接待を始めました!`
|
||||
: `対局を?[${getUserName(user)}](${conf.url}/@${user.username})さんと始めました! (強さ${form[0].value})`;
|
||||
|
||||
const res = await request.post(`${conf.api_url}/notes/create`, {
|
||||
json: { i,
|
||||
text: `${text}\n→[観戦する](${url})`
|
||||
}
|
||||
});
|
||||
|
||||
note = res.createdNote;
|
||||
//#endregion
|
||||
}
|
||||
|
||||
// ゲームが終了したとき
|
||||
if (msg.type == 'ended') {
|
||||
// ストリームから切断
|
||||
process.send({
|
||||
type: 'close'
|
||||
});
|
||||
|
||||
//#region TLに投稿する
|
||||
const user = game.user1Id == id ? game.user2 : game.user1;
|
||||
const isSettai = form[0].value === 0;
|
||||
const text = isSettai
|
||||
? msg.body.winnerId === null
|
||||
? `?[${getUserName(user)}](${conf.url}/@${user.username})さんに接待で引き分けました...`
|
||||
: msg.body.winnerId == id
|
||||
? `?[${getUserName(user)}](${conf.url}/@${user.username})さんに接待で勝ってしまいました...`
|
||||
: `?[${getUserName(user)}](${conf.url}/@${user.username})さんに接待で負けてあげました♪`
|
||||
: msg.body.winnerId === null
|
||||
? `?[${getUserName(user)}](${conf.url}/@${user.username})さんと引き分けました~`
|
||||
: msg.body.winnerId == id
|
||||
? `?[${getUserName(user)}](${conf.url}/@${user.username})さんに勝ちました♪`
|
||||
: `?[${getUserName(user)}](${conf.url}/@${user.username})さんに負けました...`;
|
||||
|
||||
await request.post(`${conf.api_url}/notes/create`, {
|
||||
json: { i,
|
||||
renoteId: note.id,
|
||||
text: text
|
||||
}
|
||||
});
|
||||
//#endregion
|
||||
|
||||
process.exit();
|
||||
}
|
||||
|
||||
// 打たれたとき
|
||||
if (msg.type == 'set') {
|
||||
onSet(msg.body);
|
||||
}
|
||||
});
|
||||
|
||||
let o: Reversi;
|
||||
let botColor: Color;
|
||||
|
||||
// 各マスの強さ
|
||||
let cellWeights;
|
||||
|
||||
/**
|
||||
* ゲーム開始時
|
||||
* @param g ゲーム情報
|
||||
*/
|
||||
function onGameStarted(g) {
|
||||
game = g;
|
||||
|
||||
// リバーシエンジン初期化
|
||||
o = new Reversi(game.settings.map, {
|
||||
isLlotheo: game.settings.isLlotheo,
|
||||
canPutEverywhere: game.settings.canPutEverywhere,
|
||||
loopedBoard: game.settings.loopedBoard
|
||||
});
|
||||
|
||||
// 各マスの価値を計算しておく
|
||||
cellWeights = o.map.map((pix, i) => {
|
||||
if (pix == 'null') return 0;
|
||||
const [x, y] = o.transformPosToXy(i);
|
||||
let count = 0;
|
||||
const get = (x, y) => {
|
||||
if (x < 0 || y < 0 || x >= o.mapWidth || y >= o.mapHeight) return 'null';
|
||||
return o.mapDataGet(o.transformXyToPos(x, y));
|
||||
};
|
||||
|
||||
if (get(x , y - 1) == 'null') count++;
|
||||
if (get(x + 1, y - 1) == 'null') count++;
|
||||
if (get(x + 1, y ) == 'null') count++;
|
||||
if (get(x + 1, y + 1) == 'null') count++;
|
||||
if (get(x , y + 1) == 'null') count++;
|
||||
if (get(x - 1, y + 1) == 'null') count++;
|
||||
if (get(x - 1, y ) == 'null') count++;
|
||||
if (get(x - 1, y - 1) == 'null') count++;
|
||||
//return Math.pow(count, 3);
|
||||
return count >= 4 ? 1 : 0;
|
||||
});
|
||||
|
||||
botColor = game.user1Id == id && game.black == 1 || game.user2Id == id && game.black == 2;
|
||||
|
||||
if (botColor) {
|
||||
think();
|
||||
}
|
||||
}
|
||||
|
||||
function onSet(x) {
|
||||
o.put(x.color, x.pos);
|
||||
|
||||
if (x.next === botColor) {
|
||||
think();
|
||||
}
|
||||
}
|
||||
|
||||
const db = {};
|
||||
|
||||
function think() {
|
||||
console.log('Thinking...');
|
||||
console.time('think');
|
||||
|
||||
const isSettai = form[0].value === 0;
|
||||
|
||||
// 接待モードのときは、全力(5手先読みくらい)で負けるようにする
|
||||
const maxDepth = isSettai ? 5 : form[0].value;
|
||||
|
||||
/**
|
||||
* Botにとってある局面がどれだけ有利か取得する
|
||||
*/
|
||||
function staticEval() {
|
||||
let score = o.canPutSomewhere(botColor).length;
|
||||
|
||||
cellWeights.forEach((weight, i) => {
|
||||
// 係数
|
||||
const coefficient = 30;
|
||||
weight = weight * coefficient;
|
||||
|
||||
const stone = o.board[i];
|
||||
if (stone === botColor) {
|
||||
// TODO: 価値のあるマスに設置されている自分の石に縦か横に接するマスは価値があると判断する
|
||||
score += weight;
|
||||
} else if (stone !== null) {
|
||||
score -= weight;
|
||||
}
|
||||
});
|
||||
|
||||
// ロセオならスコアを反転
|
||||
if (game.settings.isLlotheo) score = -score;
|
||||
|
||||
// 接待ならスコアを反転
|
||||
if (isSettai) score = -score;
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
/**
|
||||
* αβ法での探索
|
||||
*/
|
||||
const dive = (pos: number, alpha = -Infinity, beta = Infinity, depth = 0): number => {
|
||||
// 試し打ち
|
||||
o.put(o.turn, pos);
|
||||
|
||||
const key = o.board.toString();
|
||||
let cache = db[key];
|
||||
if (cache) {
|
||||
if (alpha >= cache.upper) {
|
||||
o.undo();
|
||||
return cache.upper;
|
||||
}
|
||||
if (beta <= cache.lower) {
|
||||
o.undo();
|
||||
return cache.lower;
|
||||
}
|
||||
alpha = Math.max(alpha, cache.lower);
|
||||
beta = Math.min(beta, cache.upper);
|
||||
} else {
|
||||
cache = {
|
||||
upper: Infinity,
|
||||
lower: -Infinity
|
||||
};
|
||||
}
|
||||
|
||||
const isBotTurn = o.turn === botColor;
|
||||
|
||||
// 勝った
|
||||
if (o.turn === null) {
|
||||
const winner = o.winner;
|
||||
|
||||
// 勝つことによる基本スコア
|
||||
const base = 10000;
|
||||
|
||||
let score;
|
||||
|
||||
if (game.settings.isLlotheo) {
|
||||
// 勝ちは勝ちでも、より自分の石を少なくした方が美しい勝ちだと判定する
|
||||
score = o.winner ? base - (o.blackCount * 100) : base - (o.whiteCount * 100);
|
||||
} else {
|
||||
// 勝ちは勝ちでも、より相手の石を少なくした方が美しい勝ちだと判定する
|
||||
score = o.winner ? base + (o.blackCount * 100) : base + (o.whiteCount * 100);
|
||||
}
|
||||
|
||||
// 巻き戻し
|
||||
o.undo();
|
||||
|
||||
// 接待なら自分が負けた方が高スコア
|
||||
return isSettai
|
||||
? winner !== botColor ? score : -score
|
||||
: winner === botColor ? score : -score;
|
||||
}
|
||||
|
||||
if (depth === maxDepth) {
|
||||
// 静的に評価
|
||||
const score = staticEval();
|
||||
|
||||
// 巻き戻し
|
||||
o.undo();
|
||||
|
||||
return score;
|
||||
} else {
|
||||
const cans = o.canPutSomewhere(o.turn);
|
||||
|
||||
let value = isBotTurn ? -Infinity : Infinity;
|
||||
let a = alpha;
|
||||
let b = beta;
|
||||
|
||||
// 次のターンのプレイヤーにとって最も良い手を取得
|
||||
for (const p of cans) {
|
||||
if (isBotTurn) {
|
||||
const score = dive(p, a, beta, depth + 1);
|
||||
value = Math.max(value, score);
|
||||
a = Math.max(a, value);
|
||||
if (value >= beta) break;
|
||||
} else {
|
||||
const score = dive(p, alpha, b, depth + 1);
|
||||
value = Math.min(value, score);
|
||||
b = Math.min(b, value);
|
||||
if (value <= alpha) break;
|
||||
}
|
||||
}
|
||||
|
||||
// 巻き戻し
|
||||
o.undo();
|
||||
|
||||
if (value <= alpha) {
|
||||
cache.upper = value;
|
||||
} else if (value >= beta) {
|
||||
cache.lower = value;
|
||||
} else {
|
||||
cache.upper = value;
|
||||
cache.lower = value;
|
||||
}
|
||||
|
||||
db[key] = cache;
|
||||
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* αβ法での探索(キャッシュ無し)(デバッグ用)
|
||||
*/
|
||||
const dive2 = (pos: number, alpha = -Infinity, beta = Infinity, depth = 0): number => {
|
||||
// 試し打ち
|
||||
o.put(o.turn, pos);
|
||||
|
||||
const isBotTurn = o.turn === botColor;
|
||||
|
||||
// 勝った
|
||||
if (o.turn === null) {
|
||||
const winner = o.winner;
|
||||
|
||||
// 勝つことによる基本スコア
|
||||
const base = 10000;
|
||||
|
||||
let score;
|
||||
|
||||
if (game.settings.isLlotheo) {
|
||||
// 勝ちは勝ちでも、より自分の石を少なくした方が美しい勝ちだと判定する
|
||||
score = o.winner ? base - (o.blackCount * 100) : base - (o.whiteCount * 100);
|
||||
} else {
|
||||
// 勝ちは勝ちでも、より相手の石を少なくした方が美しい勝ちだと判定する
|
||||
score = o.winner ? base + (o.blackCount * 100) : base + (o.whiteCount * 100);
|
||||
}
|
||||
|
||||
// 巻き戻し
|
||||
o.undo();
|
||||
|
||||
// 接待なら自分が負けた方が高スコア
|
||||
return isSettai
|
||||
? winner !== botColor ? score : -score
|
||||
: winner === botColor ? score : -score;
|
||||
}
|
||||
|
||||
if (depth === maxDepth) {
|
||||
// 静的に評価
|
||||
const score = staticEval();
|
||||
|
||||
// 巻き戻し
|
||||
o.undo();
|
||||
|
||||
return score;
|
||||
} else {
|
||||
const cans = o.canPutSomewhere(o.turn);
|
||||
|
||||
// 次のターンのプレイヤーにとって最も良い手を取得
|
||||
for (const p of cans) {
|
||||
if (isBotTurn) {
|
||||
alpha = Math.max(alpha, dive2(p, alpha, beta, depth + 1));
|
||||
} else {
|
||||
beta = Math.min(beta, dive2(p, alpha, beta, depth + 1));
|
||||
}
|
||||
if (alpha >= beta) break;
|
||||
}
|
||||
|
||||
// 巻き戻し
|
||||
o.undo();
|
||||
|
||||
return isBotTurn ? alpha : beta;
|
||||
}
|
||||
};
|
||||
|
||||
const cans = o.canPutSomewhere(botColor);
|
||||
const scores = cans.map(p => dive(p));
|
||||
const pos = cans[scores.indexOf(Math.max(...scores))];
|
||||
|
||||
console.log('Thinked:', pos);
|
||||
console.timeEnd('think');
|
||||
|
||||
process.send({
|
||||
type: 'put',
|
||||
pos
|
||||
});
|
||||
}
|
@ -1,233 +0,0 @@
|
||||
/**
|
||||
* -AI-
|
||||
* Botのフロントエンド(ストリームとの対話を担当)
|
||||
*
|
||||
* 対話と思考を同じプロセスで行うと、思考時間が長引いたときにストリームから
|
||||
* 切断されてしまうので、別々のプロセスで行うようにします
|
||||
*/
|
||||
|
||||
import * as childProcess from 'child_process';
|
||||
const WebSocket = require('ws');
|
||||
import * as ReconnectingWebSocket from 'reconnecting-websocket';
|
||||
import * as request from 'request-promise-native';
|
||||
import conf from '../../config';
|
||||
|
||||
// 設定 ////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* BotアカウントのAPIキー
|
||||
*/
|
||||
const i = conf.reversi_ai.i;
|
||||
|
||||
/**
|
||||
* BotアカウントのユーザーID
|
||||
*/
|
||||
const id = conf.reversi_ai.id;
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* ホームストリーム
|
||||
*/
|
||||
const homeStream = new ReconnectingWebSocket(`${conf.ws_url}/?i=${i}`, undefined, {
|
||||
constructor: WebSocket
|
||||
});
|
||||
|
||||
homeStream.on('open', () => {
|
||||
console.log('home stream opened');
|
||||
});
|
||||
|
||||
homeStream.on('close', () => {
|
||||
console.log('home stream closed');
|
||||
});
|
||||
|
||||
homeStream.on('message', message => {
|
||||
const msg = JSON.parse(message.toString());
|
||||
|
||||
// タイムライン上でなんか言われたまたは返信されたとき
|
||||
if (msg.type == 'mention' || msg.type == 'reply') {
|
||||
const note = msg.body;
|
||||
|
||||
if (note.userId == id) return;
|
||||
|
||||
// リアクションする
|
||||
request.post(`${conf.api_url}/notes/reactions/create`, {
|
||||
json: { i,
|
||||
noteId: note.id,
|
||||
reaction: 'love'
|
||||
}
|
||||
});
|
||||
|
||||
if (note.text) {
|
||||
if (note.text.indexOf('リバーシ') > -1) {
|
||||
request.post(`${conf.api_url}/notes/create`, {
|
||||
json: { i,
|
||||
replyId: note.id,
|
||||
text: '良いですよ~'
|
||||
}
|
||||
});
|
||||
|
||||
invite(note.userId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// メッセージでなんか言われたとき
|
||||
if (msg.type == 'messaging_message') {
|
||||
const message = msg.body;
|
||||
if (message.text) {
|
||||
if (message.text.indexOf('リバーシ') > -1) {
|
||||
request.post(`${conf.api_url}/messaging/messages/create`, {
|
||||
json: { i,
|
||||
userId: message.userId,
|
||||
text: '良いですよ~'
|
||||
}
|
||||
});
|
||||
|
||||
invite(message.userId);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// ユーザーを対局に誘う
|
||||
function invite(userId) {
|
||||
request.post(`${conf.api_url}/reversi/match`, {
|
||||
json: { i,
|
||||
userId: userId
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* リバーシストリーム
|
||||
*/
|
||||
const reversiStream = new ReconnectingWebSocket(`${conf.ws_url}/reversi?i=${i}`, undefined, {
|
||||
constructor: WebSocket
|
||||
});
|
||||
|
||||
reversiStream.on('open', () => {
|
||||
console.log('reversi stream opened');
|
||||
});
|
||||
|
||||
reversiStream.on('close', () => {
|
||||
console.log('reversi stream closed');
|
||||
});
|
||||
|
||||
reversiStream.on('message', message => {
|
||||
const msg = JSON.parse(message.toString());
|
||||
|
||||
// 招待されたとき
|
||||
if (msg.type == 'invited') {
|
||||
onInviteMe(msg.body.parent);
|
||||
}
|
||||
|
||||
// マッチしたとき
|
||||
if (msg.type == 'matched') {
|
||||
gameStart(msg.body);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* ゲーム開始
|
||||
* @param game ゲーム情報
|
||||
*/
|
||||
function gameStart(game) {
|
||||
// ゲームストリームに接続
|
||||
const gw = new ReconnectingWebSocket(`${conf.ws_url}/reversi-game?i=${i}&game=${game.id}`, undefined, {
|
||||
constructor: WebSocket
|
||||
});
|
||||
|
||||
gw.on('open', () => {
|
||||
console.log('reversi game stream opened');
|
||||
|
||||
// フォーム
|
||||
const form = [{
|
||||
id: 'strength',
|
||||
type: 'radio',
|
||||
label: '強さ',
|
||||
value: 2,
|
||||
items: [{
|
||||
label: '接待',
|
||||
value: 0
|
||||
}, {
|
||||
label: '弱',
|
||||
value: 1
|
||||
}, {
|
||||
label: '中',
|
||||
value: 2
|
||||
}, {
|
||||
label: '強',
|
||||
value: 3
|
||||
}, {
|
||||
label: '最強',
|
||||
value: 5
|
||||
}]
|
||||
}];
|
||||
|
||||
//#region バックエンドプロセス開始
|
||||
const ai = childProcess.fork(__dirname + '/back.js');
|
||||
|
||||
// バックエンドプロセスに情報を渡す
|
||||
ai.send({
|
||||
type: '_init_',
|
||||
game,
|
||||
form
|
||||
});
|
||||
|
||||
ai.on('message', msg => {
|
||||
if (msg.type == 'put') {
|
||||
gw.send(JSON.stringify({
|
||||
type: 'set',
|
||||
pos: msg.pos
|
||||
}));
|
||||
} else if (msg.type == 'close') {
|
||||
gw.close();
|
||||
}
|
||||
});
|
||||
|
||||
// ゲームストリームから情報が流れてきたらそのままバックエンドプロセスに伝える
|
||||
gw.on('message', message => {
|
||||
const msg = JSON.parse(message.toString());
|
||||
ai.send(msg);
|
||||
});
|
||||
//#endregion
|
||||
|
||||
// フォーム初期化
|
||||
setTimeout(() => {
|
||||
gw.send(JSON.stringify({
|
||||
type: 'init-form',
|
||||
body: form
|
||||
}));
|
||||
}, 1000);
|
||||
|
||||
// どんな設定内容の対局でも受け入れる
|
||||
setTimeout(() => {
|
||||
gw.send(JSON.stringify({
|
||||
type: 'accept'
|
||||
}));
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
gw.on('close', () => {
|
||||
console.log('reversi game stream closed');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* リバーシの対局に招待されたとき
|
||||
* @param inviter 誘ってきたユーザー
|
||||
*/
|
||||
async function onInviteMe(inviter) {
|
||||
console.log(`Someone invited me: @${inviter.username}`);
|
||||
|
||||
// 承認
|
||||
const game = await request.post(`${conf.api_url}/reversi/match`, {
|
||||
json: {
|
||||
i,
|
||||
userId: inviter.id
|
||||
}
|
||||
});
|
||||
|
||||
gameStart(game);
|
||||
}
|
@ -1 +0,0 @@
|
||||
require('./front');
|
@ -203,7 +203,7 @@ export default class Reversi {
|
||||
* 打つことができる場所を取得します
|
||||
*/
|
||||
public canPutSomewhere(color: Color): number[] {
|
||||
const result = [];
|
||||
const result: number[] = [];
|
||||
|
||||
this.board.forEach((x, i) => {
|
||||
if (this.canPut(color, i)) result.push(i);
|
||||
@ -239,7 +239,7 @@ export default class Reversi {
|
||||
const enemyColor = !color;
|
||||
|
||||
// ひっくり返せる石(の位置)リスト
|
||||
let stones = [];
|
||||
let stones: number[] = [];
|
||||
|
||||
const initPos = pos;
|
||||
|
||||
|
@ -1,439 +0,0 @@
|
||||
import * as EventEmitter from 'events';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
|
||||
import User, { IUser, init as initUser, ILocalUser } from '../../../models/user';
|
||||
|
||||
import getNoteSummary from '../../../renderers/get-note-summary';
|
||||
import getUserName from '../../../renderers/get-user-name';
|
||||
import getUserSummary from '../../../renderers/get-user-summary';
|
||||
import parseAcct from '../../../acct/parse';
|
||||
import getNotificationSummary from '../../../renderers/get-notification-summary';
|
||||
|
||||
const hmm = [
|
||||
'?',
|
||||
'ふぅ~む...?',
|
||||
'ちょっと何言ってるかわからないです',
|
||||
'「ヘルプ」と言うと利用可能な操作が確認できますよ'
|
||||
];
|
||||
|
||||
/**
|
||||
* Botの頭脳
|
||||
*/
|
||||
export default class BotCore extends EventEmitter {
|
||||
public user: IUser = null;
|
||||
|
||||
private context: Context = null;
|
||||
|
||||
constructor(user?: IUser) {
|
||||
super();
|
||||
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public clearContext() {
|
||||
this.setContext(null);
|
||||
}
|
||||
|
||||
public setContext(context: Context) {
|
||||
this.context = context;
|
||||
this.emit('updated');
|
||||
|
||||
if (context) {
|
||||
context.on('updated', () => {
|
||||
this.emit('updated');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public export() {
|
||||
return {
|
||||
user: this.user,
|
||||
context: this.context ? this.context.export() : null
|
||||
};
|
||||
}
|
||||
|
||||
protected _import(data) {
|
||||
this.user = data.user ? initUser(data.user) : null;
|
||||
this.setContext(data.context ? Context.import(this, data.context) : null);
|
||||
}
|
||||
|
||||
public static import(data) {
|
||||
const bot = new BotCore();
|
||||
bot._import(data);
|
||||
return bot;
|
||||
}
|
||||
|
||||
public async q(query: string): Promise<string> {
|
||||
if (this.context != null) {
|
||||
return await this.context.q(query);
|
||||
}
|
||||
|
||||
if (/^@[a-zA-Z0-9_]+$/.test(query)) {
|
||||
return await this.showUserCommand(query);
|
||||
}
|
||||
|
||||
switch (query) {
|
||||
case 'ping':
|
||||
return 'PONG';
|
||||
|
||||
case 'help':
|
||||
case 'ヘルプ':
|
||||
return '利用可能なコマンド一覧です:\n' +
|
||||
'help: これです\n' +
|
||||
'me: アカウント情報を見ます\n' +
|
||||
'login, signin: サインインします\n' +
|
||||
'logout, signout: サインアウトします\n' +
|
||||
'note: 投稿します\n' +
|
||||
'tl: タイムラインを見ます\n' +
|
||||
'no: 通知を見ます\n' +
|
||||
'@<ユーザー名>: ユーザーを表示します\n' +
|
||||
'\n' +
|
||||
'タイムラインや通知を見た後、「次」というとさらに遡ることができます。';
|
||||
|
||||
case 'me':
|
||||
return this.user ? `${getUserName(this.user)}としてサインインしています。\n\n${getUserSummary(this.user)}` : 'サインインしていません';
|
||||
|
||||
case 'login':
|
||||
case 'signin':
|
||||
case 'ログイン':
|
||||
case 'サインイン':
|
||||
if (this.user != null) return '既にサインインしていますよ!';
|
||||
this.setContext(new SigninContext(this));
|
||||
return await this.context.greet();
|
||||
|
||||
case 'logout':
|
||||
case 'signout':
|
||||
case 'ログアウト':
|
||||
case 'サインアウト':
|
||||
if (this.user == null) return '今はサインインしてないですよ!';
|
||||
this.signout();
|
||||
return 'ご利用ありがとうございました <3';
|
||||
|
||||
case 'note':
|
||||
case '投稿':
|
||||
if (this.user == null) return 'まずサインインしてください。';
|
||||
this.setContext(new NoteContext(this));
|
||||
return await this.context.greet();
|
||||
|
||||
case 'tl':
|
||||
case 'タイムライン':
|
||||
if (this.user == null) return 'まずサインインしてください。';
|
||||
this.setContext(new TlContext(this));
|
||||
return await this.context.greet();
|
||||
|
||||
case 'no':
|
||||
case 'notifications':
|
||||
case '通知':
|
||||
if (this.user == null) return 'まずサインインしてください。';
|
||||
this.setContext(new NotificationsContext(this));
|
||||
return await this.context.greet();
|
||||
|
||||
case 'guessing-game':
|
||||
case '数当てゲーム':
|
||||
this.setContext(new GuessingGameContext(this));
|
||||
return await this.context.greet();
|
||||
|
||||
default:
|
||||
return hmm[Math.floor(Math.random() * hmm.length)];
|
||||
}
|
||||
}
|
||||
|
||||
public signin(user: IUser) {
|
||||
this.user = user;
|
||||
this.emit('signin', user);
|
||||
this.emit('updated');
|
||||
}
|
||||
|
||||
public signout() {
|
||||
const user = this.user;
|
||||
this.user = null;
|
||||
this.emit('signout', user);
|
||||
this.emit('updated');
|
||||
}
|
||||
|
||||
public async refreshUser() {
|
||||
this.user = await User.findOne({
|
||||
_id: this.user._id
|
||||
}, {
|
||||
fields: {
|
||||
data: false
|
||||
}
|
||||
});
|
||||
|
||||
this.emit('updated');
|
||||
}
|
||||
|
||||
public async showUserCommand(q: string): Promise<string> {
|
||||
try {
|
||||
const user = await require('../endpoints/users/show')(parseAcct(q.substr(1)), this.user);
|
||||
|
||||
const text = getUserSummary(user);
|
||||
|
||||
return text;
|
||||
} catch (e) {
|
||||
return `問題が発生したようです...: ${e}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Context extends EventEmitter {
|
||||
protected bot: BotCore;
|
||||
|
||||
public abstract async greet(): Promise<string>;
|
||||
public abstract async q(query: string): Promise<string>;
|
||||
public abstract export(): any;
|
||||
|
||||
constructor(bot: BotCore) {
|
||||
super();
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
public static import(bot: BotCore, data: any) {
|
||||
if (data.type == 'guessing-game') return GuessingGameContext.import(bot, data.content);
|
||||
if (data.type == 'note') return NoteContext.import(bot, data.content);
|
||||
if (data.type == 'tl') return TlContext.import(bot, data.content);
|
||||
if (data.type == 'notifications') return NotificationsContext.import(bot, data.content);
|
||||
if (data.type == 'signin') return SigninContext.import(bot, data.content);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class SigninContext extends Context {
|
||||
private temporaryUser: ILocalUser = null;
|
||||
|
||||
public async greet(): Promise<string> {
|
||||
return 'まずユーザー名を教えてください:';
|
||||
}
|
||||
|
||||
public async q(query: string): Promise<string> {
|
||||
if (this.temporaryUser == null) {
|
||||
// Fetch user
|
||||
const user = await User.findOne({
|
||||
usernameLower: query.toLowerCase(),
|
||||
host: null
|
||||
}, {
|
||||
fields: {
|
||||
data: false
|
||||
}
|
||||
}) as ILocalUser;
|
||||
|
||||
if (user === null) {
|
||||
return `${query}というユーザーは存在しませんでした... もう一度教えてください:`;
|
||||
} else {
|
||||
this.temporaryUser = user;
|
||||
this.emit('updated');
|
||||
return `パスワードを教えてください:`;
|
||||
}
|
||||
} else {
|
||||
// Compare password
|
||||
const same = await bcrypt.compare(query, this.temporaryUser.password);
|
||||
|
||||
if (same) {
|
||||
this.bot.signin(this.temporaryUser);
|
||||
this.bot.clearContext();
|
||||
return `${getUserName(this.temporaryUser)}さん、おかえりなさい!`;
|
||||
} else {
|
||||
return `パスワードが違います... もう一度教えてください:`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public export() {
|
||||
return {
|
||||
type: 'signin',
|
||||
content: {
|
||||
temporaryUser: this.temporaryUser
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static import(bot: BotCore, data: any) {
|
||||
const context = new SigninContext(bot);
|
||||
context.temporaryUser = data.temporaryUser;
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
class NoteContext extends Context {
|
||||
public async greet(): Promise<string> {
|
||||
return '内容:';
|
||||
}
|
||||
|
||||
public async q(query: string): Promise<string> {
|
||||
await require('../endpoints/notes/create')({
|
||||
text: query
|
||||
}, this.bot.user);
|
||||
this.bot.clearContext();
|
||||
return '投稿しましたよ!';
|
||||
}
|
||||
|
||||
public export() {
|
||||
return {
|
||||
type: 'note'
|
||||
};
|
||||
}
|
||||
|
||||
public static import(bot: BotCore, data: any) {
|
||||
const context = new NoteContext(bot);
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
class TlContext extends Context {
|
||||
private next: string = null;
|
||||
|
||||
public async greet(): Promise<string> {
|
||||
return await this.getTl();
|
||||
}
|
||||
|
||||
public async q(query: string): Promise<string> {
|
||||
if (query == '次') {
|
||||
return await this.getTl();
|
||||
} else {
|
||||
this.bot.clearContext();
|
||||
return await this.bot.q(query);
|
||||
}
|
||||
}
|
||||
|
||||
private async getTl() {
|
||||
const tl = await require('../endpoints/notes/timeline')({
|
||||
limit: 5,
|
||||
untilId: this.next ? this.next : undefined
|
||||
}, this.bot.user);
|
||||
|
||||
if (tl.length > 0) {
|
||||
this.next = tl[tl.length - 1].id;
|
||||
this.emit('updated');
|
||||
|
||||
const text = tl
|
||||
.map(note => `${getUserName(note.user)}\n「${getNoteSummary(note)}」`)
|
||||
.join('\n-----\n');
|
||||
|
||||
return text;
|
||||
} else {
|
||||
return 'タイムラインに表示するものがありません...';
|
||||
}
|
||||
}
|
||||
|
||||
public export() {
|
||||
return {
|
||||
type: 'tl',
|
||||
content: {
|
||||
next: this.next,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static import(bot: BotCore, data: any) {
|
||||
const context = new TlContext(bot);
|
||||
context.next = data.next;
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
class NotificationsContext extends Context {
|
||||
private next: string = null;
|
||||
|
||||
public async greet(): Promise<string> {
|
||||
return await this.getNotifications();
|
||||
}
|
||||
|
||||
public async q(query: string): Promise<string> {
|
||||
if (query == '次') {
|
||||
return await this.getNotifications();
|
||||
} else {
|
||||
this.bot.clearContext();
|
||||
return await this.bot.q(query);
|
||||
}
|
||||
}
|
||||
|
||||
private async getNotifications() {
|
||||
const notifications = await require('../endpoints/i/notifications')({
|
||||
limit: 5,
|
||||
untilId: this.next ? this.next : undefined
|
||||
}, this.bot.user);
|
||||
|
||||
if (notifications.length > 0) {
|
||||
this.next = notifications[notifications.length - 1].id;
|
||||
this.emit('updated');
|
||||
|
||||
const text = notifications
|
||||
.map(notification => getNotificationSummary(notification))
|
||||
.join('\n-----\n');
|
||||
|
||||
return text;
|
||||
} else {
|
||||
return '通知はありません';
|
||||
}
|
||||
}
|
||||
|
||||
public export() {
|
||||
return {
|
||||
type: 'notifications',
|
||||
content: {
|
||||
next: this.next,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static import(bot: BotCore, data: any) {
|
||||
const context = new NotificationsContext(bot);
|
||||
context.next = data.next;
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
class GuessingGameContext extends Context {
|
||||
private secret: number;
|
||||
private history: number[] = [];
|
||||
|
||||
public async greet(): Promise<string> {
|
||||
this.secret = Math.floor(Math.random() * 100);
|
||||
this.emit('updated');
|
||||
return '0~100の秘密の数を当ててみてください:';
|
||||
}
|
||||
|
||||
public async q(query: string): Promise<string> {
|
||||
if (query == 'やめる') {
|
||||
this.bot.clearContext();
|
||||
return 'やめました。';
|
||||
}
|
||||
|
||||
const guess = parseInt(query, 10);
|
||||
|
||||
if (isNaN(guess)) {
|
||||
return '整数で推測してください。「やめる」と言うとゲームをやめます。';
|
||||
}
|
||||
|
||||
const firsttime = this.history.indexOf(guess) === -1;
|
||||
|
||||
this.history.push(guess);
|
||||
this.emit('updated');
|
||||
|
||||
if (this.secret < guess) {
|
||||
return firsttime ? `${guess}よりも小さいですね` : `もう一度言いますが${guess}より小さいですよ`;
|
||||
} else if (this.secret > guess) {
|
||||
return firsttime ? `${guess}よりも大きいですね` : `もう一度言いますが${guess}より大きいですよ`;
|
||||
} else {
|
||||
this.bot.clearContext();
|
||||
return `正解です🎉 (${this.history.length}回目で当てました)`;
|
||||
}
|
||||
}
|
||||
|
||||
public export() {
|
||||
return {
|
||||
type: 'guessing-game',
|
||||
content: {
|
||||
secret: this.secret,
|
||||
history: this.history
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static import(bot: BotCore, data: any) {
|
||||
const context = new GuessingGameContext(bot);
|
||||
context.secret = data.secret;
|
||||
context.history = data.history;
|
||||
return context;
|
||||
}
|
||||
}
|
@ -1,238 +0,0 @@
|
||||
import * as EventEmitter from 'events';
|
||||
import * as Router from 'koa-router';
|
||||
import * as request from 'request';
|
||||
import * as crypto from 'crypto';
|
||||
import User from '../../../../models/user';
|
||||
import config from '../../../../config';
|
||||
import BotCore from '../core';
|
||||
import _redis from '../../../../db/redis';
|
||||
import prominence = require('prominence');
|
||||
import getAcct from '../../../../acct/render';
|
||||
import parseAcct from '../../../../acct/parse';
|
||||
import getNoteSummary from '../../../../renderers/get-note-summary';
|
||||
import getUserName from '../../../../renderers/get-user-name';
|
||||
|
||||
const redis = prominence(_redis);
|
||||
|
||||
// SEE: https://developers.line.me/media/messaging-api/messages/sticker_list.pdf
|
||||
const stickers = [
|
||||
'297',
|
||||
'298',
|
||||
'299',
|
||||
'300',
|
||||
'301',
|
||||
'302',
|
||||
'303',
|
||||
'304',
|
||||
'305',
|
||||
'306',
|
||||
'307'
|
||||
];
|
||||
|
||||
class LineBot extends BotCore {
|
||||
private replyToken: string;
|
||||
|
||||
private reply(messages: any[]) {
|
||||
request.post({
|
||||
url: 'https://api.line.me/v2/bot/message/reply',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${config.line_bot.channel_access_token}`
|
||||
},
|
||||
json: {
|
||||
replyToken: this.replyToken,
|
||||
messages: messages
|
||||
}
|
||||
}, (err, res, body) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async react(ev: any): Promise<void> {
|
||||
this.replyToken = ev.replyToken;
|
||||
|
||||
switch (ev.type) {
|
||||
// メッセージ
|
||||
case 'message':
|
||||
switch (ev.message.type) {
|
||||
// テキスト
|
||||
case 'text':
|
||||
const res = await this.q(ev.message.text);
|
||||
if (res == null) return;
|
||||
// 返信
|
||||
this.reply([{
|
||||
type: 'text',
|
||||
text: res
|
||||
}]);
|
||||
break;
|
||||
|
||||
// スタンプ
|
||||
case 'sticker':
|
||||
// スタンプで返信
|
||||
this.reply([{
|
||||
type: 'sticker',
|
||||
packageId: '4',
|
||||
stickerId: stickers[Math.floor(Math.random() * stickers.length)]
|
||||
}]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// noteback
|
||||
case 'noteback':
|
||||
const data = ev.noteback.data;
|
||||
const cmd = data.split('|')[0];
|
||||
const arg = data.split('|')[1];
|
||||
switch (cmd) {
|
||||
case 'showtl':
|
||||
this.showUserTimelineNoteback(arg);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static import(data) {
|
||||
const bot = new LineBot();
|
||||
bot._import(data);
|
||||
return bot;
|
||||
}
|
||||
|
||||
public async showUserCommand(q: string) {
|
||||
const user = await require('../../endpoints/users/show')(parseAcct(q.substr(1)), this.user);
|
||||
|
||||
const acct = getAcct(user);
|
||||
const actions = [];
|
||||
|
||||
actions.push({
|
||||
type: 'noteback',
|
||||
label: 'タイムラインを見る',
|
||||
data: `showtl|${user.id}`
|
||||
});
|
||||
|
||||
if (user.twitter) {
|
||||
actions.push({
|
||||
type: 'uri',
|
||||
label: 'Twitterアカウントを見る',
|
||||
uri: `https://twitter.com/${user.twitter.screenName}`
|
||||
});
|
||||
}
|
||||
|
||||
actions.push({
|
||||
type: 'uri',
|
||||
label: 'Webで見る',
|
||||
uri: `${config.url}/@${acct}`
|
||||
});
|
||||
|
||||
this.reply([{
|
||||
type: 'template',
|
||||
altText: await super.showUserCommand(q),
|
||||
template: {
|
||||
type: 'buttons',
|
||||
thumbnailImageUrl: `${user.avatarUrl}?thumbnail&size=1024`,
|
||||
title: `${getUserName(user)} (@${acct})`,
|
||||
text: user.description || '(no description)',
|
||||
actions: actions
|
||||
}
|
||||
}]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public async showUserTimelineNoteback(userId: string) {
|
||||
const tl = await require('../../endpoints/users/notes')({
|
||||
userId: userId,
|
||||
limit: 5
|
||||
}, this.user);
|
||||
|
||||
const text = `${getUserName(tl[0].user)}さんのタイムラインはこちらです:\n\n` + tl
|
||||
.map(note => getNoteSummary(note))
|
||||
.join('\n-----\n');
|
||||
|
||||
this.reply([{
|
||||
type: 'text',
|
||||
text: text
|
||||
}]);
|
||||
}
|
||||
}
|
||||
|
||||
const handler = new EventEmitter();
|
||||
|
||||
handler.on('event', async (ev) => {
|
||||
|
||||
const sourceId = ev.source.userId;
|
||||
const sessionId = `line-bot-sessions:${sourceId}`;
|
||||
|
||||
const session = await redis.get(sessionId);
|
||||
let bot: LineBot;
|
||||
|
||||
if (session == null) {
|
||||
const user = await User.findOne({
|
||||
host: null,
|
||||
'line': {
|
||||
userId: sourceId
|
||||
}
|
||||
});
|
||||
|
||||
bot = new LineBot(user);
|
||||
|
||||
bot.on('signin', user => {
|
||||
User.update(user._id, {
|
||||
$set: {
|
||||
'line': {
|
||||
userId: sourceId
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
bot.on('signout', user => {
|
||||
User.update(user._id, {
|
||||
$set: {
|
||||
'line': {
|
||||
userId: null
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
redis.set(sessionId, JSON.stringify(bot.export()));
|
||||
} else {
|
||||
bot = LineBot.import(JSON.parse(session));
|
||||
}
|
||||
|
||||
bot.on('updated', () => {
|
||||
redis.set(sessionId, JSON.stringify(bot.export()));
|
||||
});
|
||||
|
||||
if (session != null) bot.refreshUser();
|
||||
|
||||
bot.react(ev);
|
||||
});
|
||||
|
||||
// Init router
|
||||
const router = new Router();
|
||||
|
||||
if (config.line_bot) {
|
||||
router.post('/hooks/line', ctx => {
|
||||
const sig1 = ctx.headers['x-line-signature'];
|
||||
|
||||
const hash = crypto.createHmac('SHA256', config.line_bot.channel_secret)
|
||||
.update(ctx.request.rawBody);
|
||||
|
||||
const sig2 = hash.digest('base64');
|
||||
|
||||
// シグネチャ比較
|
||||
if (sig1 === sig2) {
|
||||
ctx.request.body.events.forEach(ev => {
|
||||
handler.emit('event', ev);
|
||||
});
|
||||
} else {
|
||||
ctx.status = 400;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = router;
|
@ -1,5 +1,5 @@
|
||||
import { toUnicode } from 'punycode';
|
||||
|
||||
export default host => {
|
||||
export default (host: string) => {
|
||||
return toUnicode(host).toLowerCase();
|
||||
};
|
||||
|
@ -1,13 +1,10 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy';
|
||||
import Note from '../../../../models/note';
|
||||
|
||||
/**
|
||||
* Aggregate notes
|
||||
*/
|
||||
module.exports = params => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any) => new Promise(async (res, rej) => {
|
||||
// Get 'limit' parameter
|
||||
const [limit = 365, limitErr] = $.num.optional().range(1, 365).get(params.limit);
|
||||
if (limitErr) return rej('invalid limit param');
|
||||
|
@ -1,13 +1,10 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy';
|
||||
import User from '../../../../models/user';
|
||||
|
||||
/**
|
||||
* Aggregate users
|
||||
*/
|
||||
module.exports = params => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any) => new Promise(async (res, rej) => {
|
||||
// Get 'limit' parameter
|
||||
const [limit = 365, limitErr] = $.num.optional().range(1, 365).get(params.limit);
|
||||
if (limitErr) return rej('invalid limit param');
|
||||
|
@ -1,6 +1,3 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../../cafy-id';
|
||||
import User from '../../../../../models/user';
|
||||
import Note from '../../../../../models/note';
|
||||
@ -10,7 +7,7 @@ import Note from '../../../../../models/note';
|
||||
/**
|
||||
* Aggregate activity of a user
|
||||
*/
|
||||
module.exports = (params) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any) => new Promise(async (res, rej) => {
|
||||
// Get 'limit' parameter
|
||||
const [limit = 365, limitErr] = $.num.optional().range(1, 365).get(params.limit);
|
||||
if (limitErr) return rej('invalid limit param');
|
||||
@ -73,13 +70,13 @@ module.exports = (params) => new Promise(async (res, rej) => {
|
||||
} }
|
||||
]);
|
||||
|
||||
datas.forEach(data => {
|
||||
datas.forEach((data: any) => {
|
||||
data.date = data._id;
|
||||
delete data._id;
|
||||
|
||||
data.notes = (data.data.filter(x => x.type == 'note')[0] || { count: 0 }).count;
|
||||
data.renotes = (data.data.filter(x => x.type == 'renote')[0] || { count: 0 }).count;
|
||||
data.replies = (data.data.filter(x => x.type == 'reply')[0] || { count: 0 }).count;
|
||||
data.notes = (data.data.filter((x: any) => x.type == 'note')[0] || { count: 0 }).count;
|
||||
data.renotes = (data.data.filter((x: any) => x.type == 'renote')[0] || { count: 0 }).count;
|
||||
data.replies = (data.data.filter((x: any) => x.type == 'reply')[0] || { count: 0 }).count;
|
||||
|
||||
delete data.data;
|
||||
});
|
||||
@ -89,7 +86,7 @@ module.exports = (params) => new Promise(async (res, rej) => {
|
||||
for (let i = 0; i < limit; i++) {
|
||||
const day = new Date(new Date().setDate(new Date().getDate() - i));
|
||||
|
||||
const data = datas.filter(d =>
|
||||
const data = datas.filter((d: any) =>
|
||||
d.date.year == day.getFullYear() && d.date.month == day.getMonth() + 1 && d.date.day == day.getDate()
|
||||
)[0];
|
||||
|
||||
|
@ -8,7 +8,7 @@ import FollowedLog from '../../../../../models/followed-log';
|
||||
/**
|
||||
* Aggregate followers of a user
|
||||
*/
|
||||
module.exports = (params) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any) => new Promise(async (res, rej) => {
|
||||
// Get 'userId' parameter
|
||||
const [userId, userIdErr] = $.type(ID).get(params.userId);
|
||||
if (userIdErr) return rej('invalid userId param');
|
||||
|
@ -8,7 +8,7 @@ import FollowingLog from '../../../../../models/following-log';
|
||||
/**
|
||||
* Aggregate following of a user
|
||||
*/
|
||||
module.exports = (params) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any) => new Promise(async (res, rej) => {
|
||||
// Get 'userId' parameter
|
||||
const [userId, userIdErr] = $.type(ID).get(params.userId);
|
||||
if (userIdErr) return rej('invalid userId param');
|
||||
|
@ -1,6 +1,3 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../../cafy-id';
|
||||
import User from '../../../../../models/user';
|
||||
import Note from '../../../../../models/note';
|
||||
@ -8,7 +5,7 @@ import Note from '../../../../../models/note';
|
||||
/**
|
||||
* Aggregate note of a user
|
||||
*/
|
||||
module.exports = (params) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any) => new Promise(async (res, rej) => {
|
||||
// Get 'userId' parameter
|
||||
const [userId, userIdErr] = $.type(ID).get(params.userId);
|
||||
if (userIdErr) return rej('invalid userId param');
|
||||
@ -67,13 +64,13 @@ module.exports = (params) => new Promise(async (res, rej) => {
|
||||
} }
|
||||
]);
|
||||
|
||||
datas.forEach(data => {
|
||||
datas.forEach((data: any) => {
|
||||
data.date = data._id;
|
||||
delete data._id;
|
||||
|
||||
data.notes = (data.data.filter(x => x.type == 'note')[0] || { count: 0 }).count;
|
||||
data.renotes = (data.data.filter(x => x.type == 'renote')[0] || { count: 0 }).count;
|
||||
data.replies = (data.data.filter(x => x.type == 'reply')[0] || { count: 0 }).count;
|
||||
data.notes = (data.data.filter((x: any) => x.type == 'note')[0] || { count: 0 }).count;
|
||||
data.renotes = (data.data.filter((x: any) => x.type == 'renote')[0] || { count: 0 }).count;
|
||||
data.replies = (data.data.filter((x: any) => x.type == 'reply')[0] || { count: 0 }).count;
|
||||
|
||||
delete data.data;
|
||||
});
|
||||
@ -83,7 +80,7 @@ module.exports = (params) => new Promise(async (res, rej) => {
|
||||
for (let i = 0; i < 30; i++) {
|
||||
const day = new Date(new Date().setDate(new Date().getDate() - i));
|
||||
|
||||
const data = datas.filter(d =>
|
||||
const data = datas.filter((d: any) =>
|
||||
d.date.year == day.getFullYear() && d.date.month == day.getMonth() + 1 && d.date.day == day.getDate()
|
||||
)[0];
|
||||
|
||||
|
@ -1,17 +1,11 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../../cafy-id';
|
||||
import User from '../../../../../models/user';
|
||||
import Reaction from '../../../../../models/note-reaction';
|
||||
|
||||
/**
|
||||
* Aggregate reaction of a user
|
||||
*
|
||||
* @param {any} params
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
module.exports = (params) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any) => new Promise(async (res, rej) => {
|
||||
// Get 'userId' parameter
|
||||
const [userId, userIdErr] = $.type(ID).get(params.userId);
|
||||
if (userIdErr) return rej('invalid userId param');
|
||||
@ -48,7 +42,7 @@ module.exports = (params) => new Promise(async (res, rej) => {
|
||||
}}
|
||||
]);
|
||||
|
||||
datas.forEach(data => {
|
||||
datas.forEach((data: any) => {
|
||||
data.date = data._id;
|
||||
delete data._id;
|
||||
});
|
||||
@ -58,7 +52,7 @@ module.exports = (params) => new Promise(async (res, rej) => {
|
||||
for (let i = 0; i < 30; i++) {
|
||||
const day = new Date(new Date().setDate(new Date().getDate() - i));
|
||||
|
||||
const data = datas.filter(d =>
|
||||
const data = datas.filter((d: any) =>
|
||||
d.date.year == day.getFullYear() && d.date.month == day.getMonth() + 1 && d.date.day == day.getDate()
|
||||
)[0];
|
||||
|
||||
|
@ -1,9 +1,7 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import rndstr from 'rndstr';
|
||||
import $ from 'cafy';
|
||||
import App, { isValidNameId, pack } from '../../../../models/app';
|
||||
import { ILocalUser } from '../../../../models/user';
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
@ -60,12 +58,8 @@ import App, { isValidNameId, pack } from '../../../../models/app';
|
||||
|
||||
/**
|
||||
* Create an app
|
||||
*
|
||||
* @param {any} params
|
||||
* @param {any} user
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
module.exports = async (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'nameId' parameter
|
||||
const [nameId, nameIdErr] = $.str.pipe(isValidNameId).get(params.nameId);
|
||||
if (nameIdErr) return rej('invalid nameId param');
|
||||
|
@ -40,7 +40,7 @@ import { isValidNameId } from '../../../../../models/app';
|
||||
* @param {any} params
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
module.exports = async (params) => new Promise(async (res, rej) => {
|
||||
module.exports = async (params: any) => new Promise(async (res, rej) => {
|
||||
// Get 'nameId' parameter
|
||||
const [nameId, nameIdErr] = $.str.pipe(isValidNameId).get(params.nameId);
|
||||
if (nameIdErr) return rej('invalid nameId param');
|
||||
|
@ -1,8 +1,6 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../cafy-id';
|
||||
import App, { pack } from '../../../../models/app';
|
||||
import App, { pack, IApp } from '../../../../models/app';
|
||||
import { ILocalUser } from '../../../../models/user';
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
@ -37,7 +35,7 @@ import App, { pack } from '../../../../models/app';
|
||||
/**
|
||||
* Show an app
|
||||
*/
|
||||
module.exports = (params, user, app) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
|
||||
const isSecure = user != null && app == null;
|
||||
|
||||
// Get 'appId' parameter
|
||||
|
@ -1,12 +1,10 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import rndstr from 'rndstr';
|
||||
const crypto = require('crypto');
|
||||
import $ from 'cafy';
|
||||
import App from '../../../../models/app';
|
||||
import AuthSess from '../../../../models/auth-session';
|
||||
import AccessToken from '../../../../models/access-token';
|
||||
import { ILocalUser } from '../../../../models/user';
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
@ -33,12 +31,8 @@ import AccessToken from '../../../../models/access-token';
|
||||
|
||||
/**
|
||||
* Accept
|
||||
*
|
||||
* @param {any} params
|
||||
* @param {any} user
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'token' parameter
|
||||
const [token, tokenErr] = $.str.get(params.token);
|
||||
if (tokenErr) return rej('invalid token param');
|
||||
|
@ -44,7 +44,7 @@ import config from '../../../../../config';
|
||||
* @param {any} params
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
module.exports = (params) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any) => new Promise(async (res, rej) => {
|
||||
// Get 'appSecret' parameter
|
||||
const [appSecret, appSecretErr] = $.str.get(params.appSecret);
|
||||
if (appSecretErr) return rej('invalid appSecret param');
|
||||
|
@ -1,8 +1,6 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy';
|
||||
import AuthSess, { pack } from '../../../../../models/auth-session';
|
||||
import { ILocalUser } from '../../../../../models/user';
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
@ -46,12 +44,8 @@ import AuthSess, { pack } from '../../../../../models/auth-session';
|
||||
|
||||
/**
|
||||
* Show a session
|
||||
*
|
||||
* @param {any} params
|
||||
* @param {any} user
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'token' parameter
|
||||
const [token, tokenErr] = $.str.get(params.token);
|
||||
if (tokenErr) return rej('invalid token param');
|
||||
|
@ -49,7 +49,7 @@ import { pack } from '../../../../../models/user';
|
||||
* @param {any} params
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
module.exports = (params) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any) => new Promise(async (res, rej) => {
|
||||
// Get 'appSecret' parameter
|
||||
const [appSecret, appSecretErr] = $.str.get(params.appSecret);
|
||||
if (appSecretErr) return rej('invalid appSecret param');
|
||||
|
@ -1,9 +1,10 @@
|
||||
import DriveFile from '../../../models/drive-file';
|
||||
import { ILocalUser } from '../../../models/user';
|
||||
|
||||
/**
|
||||
* Get drive information
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Calculate drive usage
|
||||
const usage = await DriveFile
|
||||
.aggregate([{
|
||||
|
@ -1,13 +1,11 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../cafy-id';
|
||||
import DriveFile, { pack } from '../../../../models/drive-file';
|
||||
import { ILocalUser } from '../../../../models/user';
|
||||
|
||||
/**
|
||||
* Get drive files
|
||||
*/
|
||||
module.exports = async (params, user, app) => {
|
||||
module.exports = async (params: any, user: ILocalUser) => {
|
||||
// Get 'limit' parameter
|
||||
const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
|
||||
if (limitErr) throw 'invalid limit param';
|
||||
|
@ -1,15 +1,13 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import * as fs from 'fs';
|
||||
import $ from 'cafy'; import ID from '../../../../../cafy-id';
|
||||
import { validateFileName, pack } from '../../../../../models/drive-file';
|
||||
import create from '../../../../../services/drive/add-file';
|
||||
import { ILocalUser } from '../../../../../models/user';
|
||||
|
||||
/**
|
||||
* Create a file
|
||||
*/
|
||||
module.exports = async (file, params, user): Promise<any> => {
|
||||
module.exports = async (file: any, params: any, user: ILocalUser): Promise<any> => {
|
||||
if (file == null) {
|
||||
throw 'file is required';
|
||||
}
|
||||
|
@ -2,11 +2,12 @@ import $ from 'cafy'; import ID from '../../../../../cafy-id';
|
||||
import DriveFile from '../../../../../models/drive-file';
|
||||
import del from '../../../../../services/drive/delete-file';
|
||||
import { publishDriveStream } from '../../../../../publishers/stream';
|
||||
import { ILocalUser } from '../../../../../models/user';
|
||||
|
||||
/**
|
||||
* Delete a file
|
||||
*/
|
||||
module.exports = async (params, user) => {
|
||||
module.exports = async (params: any, user: ILocalUser) => {
|
||||
// Get 'fileId' parameter
|
||||
const [fileId, fileIdErr] = $.type(ID).get(params.fileId);
|
||||
if (fileIdErr) throw 'invalid fileId param';
|
||||
|
@ -1,13 +1,11 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../../cafy-id';
|
||||
import DriveFile, { pack } from '../../../../../models/drive-file';
|
||||
import { ILocalUser } from '../../../../../models/user';
|
||||
|
||||
/**
|
||||
* Find a file(s)
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'name' parameter
|
||||
const [name, nameErr] = $.str.get(params.name);
|
||||
if (nameErr) return rej('invalid name param');
|
||||
|
@ -1,13 +1,11 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../../cafy-id';
|
||||
import DriveFile, { pack } from '../../../../../models/drive-file';
|
||||
import { ILocalUser } from '../../../../../models/user';
|
||||
|
||||
/**
|
||||
* Show a file
|
||||
*/
|
||||
module.exports = async (params, user) => {
|
||||
module.exports = async (params: any, user: ILocalUser) => {
|
||||
// Get 'fileId' parameter
|
||||
const [fileId, fileIdErr] = $.type(ID).get(params.fileId);
|
||||
if (fileIdErr) throw 'invalid fileId param';
|
||||
|
@ -1,15 +1,13 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../../cafy-id';
|
||||
import DriveFolder from '../../../../../models/drive-folder';
|
||||
import DriveFile, { validateFileName, pack } from '../../../../../models/drive-file';
|
||||
import { publishDriveStream } from '../../../../../publishers/stream';
|
||||
import { ILocalUser } from '../../../../../models/user';
|
||||
|
||||
/**
|
||||
* Update a file
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'fileId' parameter
|
||||
const [fileId, fileIdErr] = $.type(ID).get(params.fileId);
|
||||
if (fileIdErr) return rej('invalid fileId param');
|
||||
|
@ -7,7 +7,7 @@ import DriveFolder, { pack } from '../../../../models/drive-folder';
|
||||
/**
|
||||
* Get drive folders
|
||||
*/
|
||||
module.exports = (params, user, app) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
|
||||
// Get 'limit' parameter
|
||||
const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
|
||||
if (limitErr) return rej('invalid limit param');
|
||||
|
@ -1,14 +1,12 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../../cafy-id';
|
||||
import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder';
|
||||
import { publishDriveStream } from '../../../../../publishers/stream';
|
||||
import { ILocalUser } from '../../../../../models/user';
|
||||
|
||||
/**
|
||||
* Create drive folder
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'name' parameter
|
||||
const [name = '無題のフォルダー', nameErr] = $.str.optional().pipe(isValidFolderName).get(params.name);
|
||||
if (nameErr) return rej('invalid name param');
|
||||
|
@ -1,13 +1,11 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../../cafy-id';
|
||||
import DriveFolder, { pack } from '../../../../../models/drive-folder';
|
||||
import { ILocalUser } from '../../../../../models/user';
|
||||
|
||||
/**
|
||||
* Find a folder(s)
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'name' parameter
|
||||
const [name, nameErr] = $.str.get(params.name);
|
||||
if (nameErr) return rej('invalid name param');
|
||||
|
@ -1,13 +1,11 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../../cafy-id';
|
||||
import DriveFolder, { pack } from '../../../../../models/drive-folder';
|
||||
import { ILocalUser } from '../../../../../models/user';
|
||||
|
||||
/**
|
||||
* Show a folder
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'folderId' parameter
|
||||
const [folderId, folderIdErr] = $.type(ID).get(params.folderId);
|
||||
if (folderIdErr) return rej('invalid folderId param');
|
||||
|
@ -1,14 +1,12 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../../cafy-id';
|
||||
import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder';
|
||||
import { publishDriveStream } from '../../../../../publishers/stream';
|
||||
import { ILocalUser } from '../../../../../models/user';
|
||||
|
||||
/**
|
||||
* Update a folder
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'folderId' parameter
|
||||
const [folderId, folderIdErr] = $.type(ID).get(params.folderId);
|
||||
if (folderIdErr) return rej('invalid folderId param');
|
||||
@ -48,7 +46,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
}
|
||||
|
||||
// Check if the circular reference will occur
|
||||
async function checkCircle(folderId) {
|
||||
async function checkCircle(folderId: any): Promise<boolean> {
|
||||
// Fetch folder
|
||||
const folder2 = await DriveFolder.findOne({
|
||||
_id: folderId
|
||||
|
@ -1,13 +1,11 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../cafy-id';
|
||||
import DriveFile, { pack } from '../../../../models/drive-file';
|
||||
import { ILocalUser } from '../../../../models/user';
|
||||
|
||||
/**
|
||||
* Get drive stream
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'limit' parameter
|
||||
const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
|
||||
if (limitErr) return rej('invalid limit param');
|
||||
|
@ -1,15 +1,12 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../cafy-id';
|
||||
import User, { pack } from '../../../../models/user';
|
||||
import User, { pack, ILocalUser } from '../../../../models/user';
|
||||
import Following from '../../../../models/following';
|
||||
import create from '../../../../services/following/create';
|
||||
|
||||
/**
|
||||
* Follow a user
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
const follower = user;
|
||||
|
||||
// Get 'userId' parameter
|
||||
|
@ -1,15 +1,12 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../cafy-id';
|
||||
import User, { pack } from '../../../../models/user';
|
||||
import User, { pack, ILocalUser } from '../../../../models/user';
|
||||
import Following from '../../../../models/following';
|
||||
import deleteFollowing from '../../../../services/following/delete';
|
||||
|
||||
/**
|
||||
* Unfollow a user
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
const follower = user;
|
||||
|
||||
// Get 'userId' parameter
|
||||
|
@ -1,11 +1,11 @@
|
||||
import $ from 'cafy'; import ID from '../../../../../cafy-id';
|
||||
import acceptFollowRequest from '../../../../../services/following/requests/accept';
|
||||
import User from '../../../../../models/user';
|
||||
import User, { ILocalUser } from '../../../../../models/user';
|
||||
|
||||
/**
|
||||
* Accept a follow request
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'userId' parameter
|
||||
const [followerId, followerIdErr] = $.type(ID).get(params.userId);
|
||||
if (followerIdErr) return rej('invalid userId param');
|
||||
|
@ -1,11 +1,11 @@
|
||||
import $ from 'cafy'; import ID from '../../../../../cafy-id';
|
||||
import cancelFollowRequest from '../../../../../services/following/requests/cancel';
|
||||
import User, { pack } from '../../../../../models/user';
|
||||
import User, { pack, ILocalUser } from '../../../../../models/user';
|
||||
|
||||
/**
|
||||
* Cancel a follow request
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'userId' parameter
|
||||
const [followeeId, followeeIdErr] = $.type(ID).get(params.userId);
|
||||
if (followeeIdErr) return rej('invalid userId param');
|
||||
|
@ -1,10 +1,11 @@
|
||||
//import $ from 'cafy'; import ID from '../../../../../cafy-id';
|
||||
import FollowRequest, { pack } from '../../../../../models/follow-request';
|
||||
import { ILocalUser } from '../../../../../models/user';
|
||||
|
||||
/**
|
||||
* Get all pending received follow requests
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
const reqs = await FollowRequest.find({
|
||||
followeeId: user._id
|
||||
});
|
||||
|
@ -1,11 +1,11 @@
|
||||
import $ from 'cafy'; import ID from '../../../../../cafy-id';
|
||||
import rejectFollowRequest from '../../../../../services/following/requests/reject';
|
||||
import User from '../../../../../models/user';
|
||||
import User, { ILocalUser } from '../../../../../models/user';
|
||||
|
||||
/**
|
||||
* Reject a follow request
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'userId' parameter
|
||||
const [followerId, followerIdErr] = $.type(ID).get(params.userId);
|
||||
if (followerIdErr) return rej('invalid userId param');
|
||||
|
@ -1,10 +1,11 @@
|
||||
import $ from 'cafy'; import ID from '../../../../cafy-id';
|
||||
import Following from '../../../../models/following';
|
||||
import { ILocalUser } from '../../../../models/user';
|
||||
|
||||
/**
|
||||
* Stalk a user
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
const follower = user;
|
||||
|
||||
// Get 'userId' parameter
|
||||
|
@ -1,10 +1,11 @@
|
||||
import $ from 'cafy'; import ID from '../../../../cafy-id';
|
||||
import Following from '../../../../models/following';
|
||||
import { ILocalUser } from '../../../../models/user';
|
||||
|
||||
/**
|
||||
* Unstalk a user
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
const follower = user;
|
||||
|
||||
// Get 'userId' parameter
|
||||
|
@ -45,7 +45,10 @@ module.exports = () => new Promise(async (res, rej) => {
|
||||
return res([]);
|
||||
}
|
||||
|
||||
const tags = [];
|
||||
const tags: Array<{
|
||||
name: string;
|
||||
count: number;
|
||||
}> = [];
|
||||
|
||||
// カウント
|
||||
data.map(x => x._id).forEach(x => {
|
||||
|
@ -1,12 +1,10 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import User, { pack } from '../../../models/user';
|
||||
import User, { pack, ILocalUser } from '../../../models/user';
|
||||
import { IApp } from '../../../models/app';
|
||||
|
||||
/**
|
||||
* Show myself
|
||||
*/
|
||||
module.exports = (params, user, app) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
|
||||
const isSecure = user != null && app == null;
|
||||
|
||||
// Serialize
|
||||
|
@ -1,11 +1,8 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy';
|
||||
import * as speakeasy from 'speakeasy';
|
||||
import User from '../../../../../models/user';
|
||||
import User, { ILocalUser } from '../../../../../models/user';
|
||||
|
||||
module.exports = async (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'token' parameter
|
||||
const [token, tokenErr] = $.str.get(params.token);
|
||||
if (tokenErr) return rej('invalid token param');
|
||||
|
@ -1,14 +1,11 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import * as speakeasy from 'speakeasy';
|
||||
import * as QRCode from 'qrcode';
|
||||
import User from '../../../../../models/user';
|
||||
import User, { ILocalUser } from '../../../../../models/user';
|
||||
import config from '../../../../../config';
|
||||
|
||||
module.exports = async (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'password' parameter
|
||||
const [password, passwordErr] = $.str.get(params.password);
|
||||
if (passwordErr) return rej('invalid password param');
|
||||
|
@ -1,11 +1,8 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import User from '../../../../../models/user';
|
||||
import User, { ILocalUser } from '../../../../../models/user';
|
||||
|
||||
module.exports = async (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'password' parameter
|
||||
const [password, passwordErr] = $.str.get(params.password);
|
||||
if (passwordErr) return rej('invalid password param');
|
||||
|
@ -1,14 +1,12 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy';
|
||||
import AccessToken from '../../../../models/access-token';
|
||||
import { pack } from '../../../../models/app';
|
||||
import { ILocalUser } from '../../../../models/user';
|
||||
|
||||
/**
|
||||
* Get authorized apps of my account
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'limit' parameter
|
||||
const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
|
||||
if (limitErr) return rej('invalid limit param');
|
||||
|
@ -1,14 +1,11 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import User from '../../../../models/user';
|
||||
import User, { ILocalUser } from '../../../../models/user';
|
||||
|
||||
/**
|
||||
* Change password
|
||||
*/
|
||||
module.exports = async (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'currentPasword' parameter
|
||||
const [currentPassword, currentPasswordErr] = $.str.get(params.currentPasword);
|
||||
if (currentPasswordErr) return rej('invalid currentPasword param');
|
||||
|
@ -1,13 +1,11 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../cafy-id';
|
||||
import Favorite, { pack } from '../../../../models/favorite';
|
||||
import { ILocalUser } from '../../../../models/user';
|
||||
|
||||
/**
|
||||
* Get favorited notes
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'limit' parameter
|
||||
const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
|
||||
if (limitErr) return rej('invalid limit param');
|
||||
|
@ -1,17 +1,15 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../cafy-id';
|
||||
import Notification from '../../../../models/notification';
|
||||
import Mute from '../../../../models/mute';
|
||||
import { pack } from '../../../../models/notification';
|
||||
import { getFriendIds } from '../../common/get-friends';
|
||||
import read from '../../common/read-notification';
|
||||
import { ILocalUser } from '../../../../models/user';
|
||||
|
||||
/**
|
||||
* Get notifications
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'following' parameter
|
||||
const [following = false, followingError] =
|
||||
$.bool.optional().get(params.following);
|
||||
|
@ -1,15 +1,12 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../cafy-id';
|
||||
import User from '../../../../models/user';
|
||||
import User, { ILocalUser } from '../../../../models/user';
|
||||
import Note from '../../../../models/note';
|
||||
import { pack } from '../../../../models/user';
|
||||
|
||||
/**
|
||||
* Pin note
|
||||
*/
|
||||
module.exports = async (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'noteId' parameter
|
||||
const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
|
||||
if (noteIdErr) return rej('invalid noteId param');
|
||||
|
@ -1,16 +1,13 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import User from '../../../../models/user';
|
||||
import User, { ILocalUser } from '../../../../models/user';
|
||||
import event from '../../../../publishers/stream';
|
||||
import generateUserToken from '../../common/generate-native-user-token';
|
||||
|
||||
/**
|
||||
* Regenerate native token
|
||||
*/
|
||||
module.exports = async (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'password' parameter
|
||||
const [password, passwordErr] = $.str.get(params.password);
|
||||
if (passwordErr) return rej('invalid password param');
|
||||
|
@ -1,13 +1,11 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../cafy-id';
|
||||
import Signin, { pack } from '../../../../models/signin';
|
||||
import { ILocalUser } from '../../../../models/user';
|
||||
|
||||
/**
|
||||
* Get signin history of my account
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'limit' parameter
|
||||
const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
|
||||
if (limitErr) return rej('invalid limit param');
|
||||
|
@ -1,16 +1,14 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../cafy-id';
|
||||
import User, { isValidName, isValidDescription, isValidLocation, isValidBirthday, pack } from '../../../../models/user';
|
||||
import User, { isValidName, isValidDescription, isValidLocation, isValidBirthday, pack, ILocalUser } from '../../../../models/user';
|
||||
import event from '../../../../publishers/stream';
|
||||
import DriveFile from '../../../../models/drive-file';
|
||||
import acceptAllFollowRequests from '../../../../services/following/requests/accept-all';
|
||||
import { IApp } from '../../../../models/app';
|
||||
|
||||
/**
|
||||
* Update myself
|
||||
*/
|
||||
module.exports = async (params, user, app) => new Promise(async (res, rej) => {
|
||||
module.exports = async (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
|
||||
const isSecure = user != null && app == null;
|
||||
|
||||
const updates = {} as any;
|
||||
|
@ -1,14 +1,11 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy';
|
||||
import User from '../../../../models/user';
|
||||
import User, { ILocalUser } from '../../../../models/user';
|
||||
import event from '../../../../publishers/stream';
|
||||
|
||||
/**
|
||||
* Update myself
|
||||
*/
|
||||
module.exports = async (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'name' parameter
|
||||
const [name, nameErr] = $.str.get(params.name);
|
||||
if (nameErr) return rej('invalid name param');
|
||||
@ -17,7 +14,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
|
||||
const [value, valueErr] = $.any.nullable().get(params.value);
|
||||
if (valueErr) return rej('invalid value param');
|
||||
|
||||
const x = {};
|
||||
const x: any = {};
|
||||
x[`clientSettings.${name}`] = value;
|
||||
|
||||
await User.update(user._id, {
|
||||
|
@ -1,8 +1,8 @@
|
||||
import $ from 'cafy';
|
||||
import User from '../../../../models/user';
|
||||
import User, { ILocalUser } from '../../../../models/user';
|
||||
import event from '../../../../publishers/stream';
|
||||
|
||||
module.exports = async (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'home' parameter
|
||||
const [home, homeErr] = $.arr(
|
||||
$.obj.strict()
|
||||
|
@ -1,8 +1,8 @@
|
||||
import $ from 'cafy';
|
||||
import User from '../../../../models/user';
|
||||
import User, { ILocalUser } from '../../../../models/user';
|
||||
import event from '../../../../publishers/stream';
|
||||
|
||||
module.exports = async (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'home' parameter
|
||||
const [home, homeErr] = $.arr(
|
||||
$.obj.strict()
|
||||
|
@ -1,8 +1,8 @@
|
||||
import $ from 'cafy';
|
||||
import User from '../../../../models/user';
|
||||
import User, { ILocalUser } from '../../../../models/user';
|
||||
import event from '../../../../publishers/stream';
|
||||
|
||||
module.exports = async (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'id' parameter
|
||||
const [id, idErr] = $.str.get(params.id);
|
||||
if (idErr) return rej('invalid id param');
|
||||
@ -18,7 +18,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
|
||||
//#region Desktop home
|
||||
if (widget == null && user.clientSettings.home) {
|
||||
const desktopHome = user.clientSettings.home;
|
||||
widget = desktopHome.find(w => w.id == id);
|
||||
widget = desktopHome.find((w: any) => w.id == id);
|
||||
if (widget) {
|
||||
widget.data = data;
|
||||
|
||||
@ -34,7 +34,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
|
||||
//#region Mobile home
|
||||
if (widget == null && user.clientSettings.mobileHome) {
|
||||
const mobileHome = user.clientSettings.mobileHome;
|
||||
widget = mobileHome.find(w => w.id == id);
|
||||
widget = mobileHome.find((w: any) => w.id == id);
|
||||
if (widget) {
|
||||
widget.data = data;
|
||||
|
||||
@ -50,8 +50,8 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
|
||||
//#region Deck
|
||||
if (widget == null && user.clientSettings.deck && user.clientSettings.deck.columns) {
|
||||
const deck = user.clientSettings.deck;
|
||||
deck.columns.filter(c => c.type == 'widgets').forEach(c => {
|
||||
c.widgets.forEach(w => {
|
||||
deck.columns.filter((c: any) => c.type == 'widgets').forEach((c: any) => {
|
||||
c.widgets.forEach((w: any) => {
|
||||
if (w.id == id) widget = w;
|
||||
});
|
||||
});
|
||||
|
@ -1,15 +1,13 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy';
|
||||
import History from '../../../../models/messaging-history';
|
||||
import Mute from '../../../../models/mute';
|
||||
import { pack } from '../../../../models/messaging-message';
|
||||
import { ILocalUser } from '../../../../models/user';
|
||||
|
||||
/**
|
||||
* Show messaging history
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'limit' parameter
|
||||
const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
|
||||
if (limitErr) return rej('invalid limit param');
|
||||
|
@ -1,13 +1,13 @@
|
||||
import $ from 'cafy'; import ID from '../../../../cafy-id';
|
||||
import Message from '../../../../models/messaging-message';
|
||||
import User from '../../../../models/user';
|
||||
import User, { ILocalUser } from '../../../../models/user';
|
||||
import { pack } from '../../../../models/messaging-message';
|
||||
import read from '../../common/read-messaging-message';
|
||||
|
||||
/**
|
||||
* Get messages
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'userId' parameter
|
||||
const [recipientId, recipientIdErr] = $.type(ID).get(params.userId);
|
||||
if (recipientIdErr) return rej('invalid userId param');
|
||||
|
@ -1,11 +1,8 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../../cafy-id';
|
||||
import Message from '../../../../../models/messaging-message';
|
||||
import { isValidText } from '../../../../../models/messaging-message';
|
||||
import History from '../../../../../models/messaging-history';
|
||||
import User from '../../../../../models/user';
|
||||
import User, { ILocalUser } from '../../../../../models/user';
|
||||
import Mute from '../../../../../models/mute';
|
||||
import DriveFile from '../../../../../models/drive-file';
|
||||
import { pack } from '../../../../../models/messaging-message';
|
||||
@ -17,7 +14,7 @@ import config from '../../../../../config';
|
||||
/**
|
||||
* Create a message
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'userId' parameter
|
||||
const [recipientId, recipientIdErr] = $.type(ID).get(params.userId);
|
||||
if (recipientIdErr) return rej('invalid userId param');
|
||||
|
@ -38,7 +38,7 @@ const client = require('../../../../built/client/meta.json');
|
||||
/**
|
||||
* Show core info
|
||||
*/
|
||||
module.exports = (params) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any) => new Promise(async (res, rej) => {
|
||||
const meta: any = (await Meta.findOne()) || {};
|
||||
|
||||
res({
|
||||
|
@ -1,14 +1,11 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../cafy-id';
|
||||
import User from '../../../../models/user';
|
||||
import User, { ILocalUser } from '../../../../models/user';
|
||||
import Mute from '../../../../models/mute';
|
||||
|
||||
/**
|
||||
* Mute a user
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
const muter = user;
|
||||
|
||||
// Get 'userId' parameter
|
||||
|
@ -1,14 +1,11 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../cafy-id';
|
||||
import User from '../../../../models/user';
|
||||
import User, { ILocalUser } from '../../../../models/user';
|
||||
import Mute from '../../../../models/mute';
|
||||
|
||||
/**
|
||||
* Unmute a user
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
const muter = user;
|
||||
|
||||
// Get 'userId' parameter
|
||||
|
@ -1,15 +1,12 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../cafy-id';
|
||||
import Mute from '../../../../models/mute';
|
||||
import { pack } from '../../../../models/user';
|
||||
import { pack, ILocalUser } from '../../../../models/user';
|
||||
import { getFriendIds } from '../../common/get-friends';
|
||||
|
||||
/**
|
||||
* Get muted users of a user
|
||||
*/
|
||||
module.exports = (params, me) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'iknow' parameter
|
||||
const [iknow = false, iknowErr] = $.bool.optional().get(params.iknow);
|
||||
if (iknowErr) return rej('invalid iknow param');
|
||||
|
@ -1,13 +1,11 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy';
|
||||
import App, { pack } from '../../../../models/app';
|
||||
import { ILocalUser } from '../../../../models/user';
|
||||
|
||||
/**
|
||||
* Get my apps
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'limit' parameter
|
||||
const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
|
||||
if (limitErr) return rej('invalid limit param');
|
||||
|
@ -7,7 +7,7 @@ import Note, { pack } from '../../../models/note';
|
||||
/**
|
||||
* Get all notes
|
||||
*/
|
||||
module.exports = (params) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any) => new Promise(async (res, rej) => {
|
||||
// Get 'local' parameter
|
||||
const [local, localErr] = $.bool.optional().get(params.local);
|
||||
if (localErr) return rej('invalid local param');
|
||||
|
@ -1,13 +1,11 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../cafy-id';
|
||||
import Note, { pack } from '../../../../models/note';
|
||||
import Note, { pack, INote } from '../../../../models/note';
|
||||
import { ILocalUser } from '../../../../models/user';
|
||||
|
||||
/**
|
||||
* Show conversation of a note
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'noteId' parameter
|
||||
const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
|
||||
if (noteIdErr) return rej('invalid noteId param');
|
||||
@ -29,10 +27,10 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
return rej('note not found');
|
||||
}
|
||||
|
||||
const conversation = [];
|
||||
const conversation: INote[] = [];
|
||||
let i = 0;
|
||||
|
||||
async function get(id) {
|
||||
async function get(id: any) {
|
||||
i++;
|
||||
const p = await Note.findOne({ _id: id });
|
||||
|
||||
|
@ -1,9 +1,6 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import $ from 'cafy'; import ID from '../../../../cafy-id';
|
||||
import Note, { INote, isValidText, isValidCw, pack } from '../../../../models/note';
|
||||
import User, { ILocalUser } from '../../../../models/user';
|
||||
import User, { ILocalUser, IUser } from '../../../../models/user';
|
||||
import DriveFile from '../../../../models/drive-file';
|
||||
import create from '../../../../services/note/create';
|
||||
import { IApp } from '../../../../models/app';
|
||||
@ -11,7 +8,7 @@ import { IApp } from '../../../../models/app';
|
||||
/**
|
||||
* Create a note
|
||||
*/
|
||||
module.exports = (params, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
|
||||
module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
|
||||
// Get 'visibility' parameter
|
||||
const [visibility = 'public', visibilityErr] = $.str.optional().or(['public', 'home', 'followers', 'specified', 'private']).get(params.visibility);
|
||||
if (visibilityErr) return rej('invalid visibility');
|
||||
@ -20,7 +17,7 @@ module.exports = (params, user: ILocalUser, app: IApp) => new Promise(async (res
|
||||
const [visibleUserIds, visibleUserIdsErr] = $.arr($.type(ID)).optional().unique().min(1).get(params.visibleUserIds);
|
||||
if (visibleUserIdsErr) return rej('invalid visibleUserIds');
|
||||
|
||||
let visibleUsers = [];
|
||||
let visibleUsers: IUser[] = [];
|
||||
if (visibleUserIds !== undefined) {
|
||||
visibleUsers = await Promise.all(visibleUserIds.map(id => User.findOne({
|
||||
_id: id
|
||||
@ -132,7 +129,7 @@ module.exports = (params, user: ILocalUser, app: IApp) => new Promise(async (res
|
||||
if (pollErr) return rej('invalid poll');
|
||||
|
||||
if (poll) {
|
||||
(poll as any).choices = (poll as any).choices.map((choice, i) => ({
|
||||
(poll as any).choices = (poll as any).choices.map((choice: string, i: number) => ({
|
||||
id: i, // IDを付与
|
||||
text: choice.trim(),
|
||||
votes: 0
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user