Skip to content
Permalink
Browse files

More promises

  • Loading branch information...
jkelin committed Mar 16, 2019
1 parent cc2ab13 commit f39fb74ed5bb8b241d29f981f6ed0f9e7b9b5774
Showing with 205 additions and 148 deletions.
  1. +1 −1 package.json
  2. +56 −40 src/chat.ts
  3. +2 −2 src/discord.ts
  4. +104 −80 src/index.ts
  5. +10 −5 src/players.ts
  6. +1 −1 src/scripts/export_anticheat_data.ts
  7. +3 −1 src/scripts/normalize_names.ts
  8. +1 −1 src/serverQuery.ts
  9. +24 −16 src/tracker.ts
  10. +3 −1 tslint.json
@@ -84,7 +84,7 @@
"script:normalize_names": "ts-node --files src/scripts/normalize_names.ts",
"script:prod:normalize_names": "node src/scripts/normalize_names.js",
"typecheck": "tsc --noEmit",
"lint": "tslint -c tslint.json src/**/*.ts",
"lint": "tslint --project ./ -c tslint.json src/**/*.ts",
"lint:fix": "tslint --fix -c tslint.json src/**/*.ts",
"build": "tsc"
},
@@ -28,7 +28,7 @@ const axiosInstance = axios.create({
import 'rxjs/operator/debounceTime';

const chatCache: Record<string, IChatMessage[]> = {};
const activeChatRequests = {};
const activeChatRequests: Record<string, Promise<IChatMessage[]>> = {};

function createRedisBucket(date: Date | moment.Moment) {
return moment(date).format('YYYY-MM-DDTHH');
@@ -56,10 +56,14 @@ export async function loadChatCacheFromRedis() {
}

function arraysMatch<T>(a: T[], b: T[]) {
if (a.length !== b.length) { return false; }
if (a.length !== b.length) {
return false;
}

for (const i in a) {
if (a[i] !== b[i]) { return false; }
if (a[i] !== b[i]) {
return false;
}
}

return true;
@@ -129,11 +133,15 @@ function getServerChat(serverId: string, server: string, username: string, passw
for (let i = 0; i < contents.length; i++) {
const x = contents[i];

if (x.type !== 'text' || !x.data || !x.data.trim()) { continue; }
if (x.type !== 'text' || !x.data || !x.data.trim()) {
continue;
}

const groups = /^>( ([^:]{1,29}):)?(.*)$/.exec(x.data.trim());

if (!groups || groups.length < 4) { continue; }
if (!groups || groups.length < 4) {
continue;
}

messages.push({
user: (groups[2] || '').trim() || 'WebAdmin',
@@ -145,7 +153,9 @@ function getServerChat(serverId: string, server: string, username: string, passw
})
.then(m => {
let cache = chatCache[serverId];
if (!cache) { cache = chatCache[serverId] = []; }
if (!cache) {
cache = chatCache[serverId] = [];
}

const hash = (x: { user: string; message: string }) => hashStringIntoNumber(x.user + x.message);

@@ -170,42 +180,48 @@ function getServerChat(serverId: string, server: string, username: string, passw
});
}

export function startQueryingServersForChat() {
return setInterval(() => {
Server.where('chat', { $exists: true })
.where('chat.enabled')
.equals(true)
.find((err, servers: IServerModel[]) => {
if (err) { throw err; }

servers.forEach(server => {
if (activeChatRequests[server._id]) { return; }

activeChatRequests[server._id] = getServerChat(
server._id,
server.chat.server,
server.chat.username,
server.chat.password
)
.then(x => {
console.debug('Got server chat from', { id: server._id });

server.chat.ok = true;
server.save();
delete activeChatRequests[server._id];
})
.catch(x => {
console.info('Error getting chat from ' + server._id, x.message);

server.chat.ok = false;
server.save();
delete activeChatRequests[server._id];
});
});
});
}, 1000);
async function queryServersForChat() {
const servers: IServerModel[] = await Server.where('chat', { $exists: true })
.where('chat.enabled')
.equals(true)
.find()
.exec();

async function serverChatPromise(server: IServerModel) {
try {
const chat = await getServerChat(server._id, server.chat.server, server.chat.username, server.chat.password);

console.debug('Got server chat from', { id: server._id });

server.chat.ok = true;
await server.save();
delete activeChatRequests[server._id];

return chat;
} catch (ex) {
console.info('Error getting chat from ' + server._id, ex.message);

server.chat.ok = false;
await server.save();
delete activeChatRequests[server._id];

return [];
}
}

const promises: Array<Promise<unknown>> = servers
.filter(server => !activeChatRequests[server._id])
.map(server => (activeChatRequests[server._id] = serverChatPromise(server)));

return Promise.all(promises);
}

export async function startQueryingServersForChat() {
while (true) {
await new Promise(resolve => setTimeout(resolve, 1000));
await queryServersForChat();
}
}
export function getChatFor(server: string) {
return (chatCache[server] || []).filter(x => x.when.getTime() > Date.now() - 2 * 60 * 60 * 1000);
}
@@ -29,10 +29,10 @@ if (RUN_DISCORD && webhookId && webhookToken) {
});
}

if (RUN_DISCORD && token) {
export async function readDiscord(discordToken: string) {
const client = new Discord.Client();
client.listenerCount = () => 0;
client.login(token);
await client.login(discordToken);

client.on('message', message => {
if (message.channel.id === channelId && !message.author.bot) {
@@ -29,88 +29,112 @@ const RUN_WEB = process.env.RUN_WEB === 'true';
const RUN_SERVER_QUERY = process.env.RUN_SERVER_QUERY === 'true';
const RUN_CHAT_QUERY = process.env.RUN_CHAT_QUERY === 'true';

const app = express();

app.use(morgan('tiny'));

if (process.env.SENTRY_DSN) {
Sentry.init({
dsn: process.env.SENTRY_DSN,
release: process.env.SENTRY_RELEASE,
async function main() {
const promises: Array<Promise<unknown>> = [];

const app = express();

app.use(morgan('tiny'));

if (process.env.SENTRY_DSN) {
Sentry.init({
dsn: process.env.SENTRY_DSN,
release: process.env.SENTRY_RELEASE,
});

app.use(Sentry.Handlers.requestHandler());
}

const server = new http.Server(app);

if (RUN_WEB) {
app.use(compression());
app.use(
cors({
credentials: true,
origin: '*',
})
);

initSocketIO(server);

app.set('views', path.join(__dirname, '../views'));
app.engine('handlebars', exphbs({ defaultLayout: 'main', helpers: handlebarsHelpers }));
app.set('view engine', 'handlebars');

// app.use(bodyParser.json());
// app.use(bodyParser.urlencoded({extended: true}));

app.use('/public', express.static(path.join(__dirname, '../public'), { maxAge: '365d' }));
app.use('/static', express.static(path.join(__dirname, '../static'), { maxAge: '365d' }));

const ticker = require('./ticker');
const servers = require('./servers');
const players = require('./players');
const matches = require('./matches');
const pages = require('./pages');
const search = require('./search');
const tracker = require('./tracker');

app.use('/', players.router);
app.use('/', servers.router);
app.use('/', ticker.router);
app.use('/', matches.router);
app.use('/', pages.router);
app.use('/', search.router);
app.use('/', tracker.router);
}

if (RUN_SERVER_QUERY) {
setInterval(queryLiveServers, 5 * 1000);
}

if (process.env.SENTRY_DSN) {
app.use(Sentry.Handlers.errorHandler());
}

app.use((err: Error, req: Request, res: Response, next: () => void) => {
console.error('App error:', err);

res.statusCode = 500;
res.end(err);
});

app.use(Sentry.Handlers.requestHandler());
}

const server = new http.Server(app);

if (RUN_WEB) {
app.use(compression());
app.use(
cors({
credentials: true,
origin: '*',
})
);

initSocketIO(server);

app.set('views', path.join(__dirname, '../views'));
app.engine('handlebars', exphbs({ defaultLayout: 'main', helpers: handlebarsHelpers }));
app.set('view engine', 'handlebars');

// app.use(bodyParser.json());
// app.use(bodyParser.urlencoded({extended: true}));

app.use('/public', express.static(path.join(__dirname, '../public'), { maxAge: '365d' }));
app.use('/static', express.static(path.join(__dirname, '../static'), { maxAge: '365d' }));

const ticker = require('./ticker');
const servers = require('./servers');
const players = require('./players');
const matches = require('./matches');
const pages = require('./pages');
const search = require('./search');
const tracker = require('./tracker');

app.use('/', players.router);
app.use('/', servers.router);
app.use('/', ticker.router);
app.use('/', matches.router);
app.use('/', pages.router);
app.use('/', search.router);
app.use('/', tracker.router);
}

if (RUN_SERVER_QUERY) {
setInterval(queryLiveServers, 5 * 1000);
}

if (process.env.SENTRY_DSN) {
app.use(Sentry.Handlers.errorHandler());
if (RUN_WEB || RUN_SERVER_QUERY) {
server.listen(process.env.PORT || 5000, () => {
const host = server.address().address;
const port = server.address().port;

console.info('App listening', { host, port });
});
}

if (RUN_CHAT_QUERY) {
promises.push(startQueryingServersForChat());
}

if (redisClient) {
promises.push(loadChatCacheFromRedis());
subscribeToMessagesFromRedis();
publishMessagesToRedis();
}

await Promise.all(promises);
}

app.use((err: Error, req: Request, res: Response, next: () => void) => {
console.error('App error:', err);
res.statusCode = 500;
res.end(err);
const mainPromise: any = main()
.catch(async error => {
if (process.env.SENTRY_DSN) {
const id = Sentry.captureException(error);
console.info("Sentry error captured as", id);
console.info(error);

await new Promise(resolve => setTimeout(resolve, 1000));
} else {
console.info("An error has occured but sentry is not connected");
console.error(error);
}
})
.then(() => {
console.info("All done");
});

if (RUN_WEB || RUN_SERVER_QUERY) {
server.listen(process.env.PORT || 5000, () => {
const host = server.address().address;
const port = server.address().port;

console.info('App listening', { host, port });
});
}

if (RUN_CHAT_QUERY) {
startQueryingServersForChat();
}

if (redisClient) {
loadChatCacheFromRedis();
subscribeToMessagesFromRedis();
publishMessagesToRedis();
}
@@ -10,7 +10,9 @@ import * as asyncHandler from 'express-async-handler';
const router = express.Router();

async function findRelatedNicknames(name: string) {
const player = await Player.find({ _id: name }).findOne();
const player = await Player.find({ _id: name })
.findOne()
.exec();

if (!player) {
return null;
@@ -36,7 +38,9 @@ async function findRelatedNicknames(name: string) {

async function findRelatedNicknamesFromIdentities(names: string[], ips: string[]) {
names = names.map(cleanPlayerName);
const identities = await Identity.find({ namesAndIps: { $in: [...names, ...ips] } }, { names: true }).findOne();
const identities = await Identity.find({ namesAndIps: { $in: [...names, ...ips] } }, { names: true })
.findOne()
.exec();

if (identities) {
return sortBy(toPairs(identities.names), x => -x[1])
@@ -52,7 +56,9 @@ async function findRelatedNicknamesFromPlayers(name: string, ip?: string) {
return null;
}

const players = await Player.find({ ip: { $regex: new RegExp(ip) } }, { _id: true, minutesonline: true }).find();
const players = await Player.find({ ip: { $regex: new RegExp(ip) } }, { _id: true, minutesonline: true })
.find()
.exec();

if (players) {
return sortBy(players, x => -x.minutesonline)
@@ -229,8 +235,7 @@ router.get(
score: -1,
},
},
])
.exec();
]).exec();

res.render('personas', {
data: personas,
Oops, something went wrong.

0 comments on commit f39fb74

Please sign in to comment.
You can’t perform that action at this time.