Skip to content

Commit

Permalink
Merge pull request #82 from Agadar/dev-1.5.0
Browse files Browse the repository at this point in the history
Dev 1.5.0
  • Loading branch information
Agadar authored Dec 23, 2017
2 parents 085a294 + 085bea6 commit a0bea40
Show file tree
Hide file tree
Showing 17 changed files with 374 additions and 120 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dank-times-bot",
"version": "1.4.0",
"version": "1.5.0",
"description": "This Telegram bot keeps track of 'dank' times such as 13:37 and 04:20, and awards points to users who call them out.",
"main": "built/main.js",
"scripts": {
Expand Down
11 changes: 11 additions & 0 deletions releases.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
[
{
"version": "1.5.0",
"date": "2017-12-23",
"changes": [
"Users whose score is 0 are now removed from the leaderboard on nightly updates",
"When a user is the only user in a chat, they no longer benefit from handicap mode",
"The bot now prints its version in the console on launch",
"Gave the developer (i.e. me) admin-level access to all bot commands",
"Fixed a bug that caused hardcore mode to set a user's score to 0 if their score was negative"
]
},
{
"version": "1.4.0",
"date": "2017-12-22",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { assert } from "chai";
import "mocha";
import * as moment from "moment-timezone";

import { ChatRegistryMock } from "../chat-registry/chat-registry-mock";
import { Chat } from "../chat/chat";
import { DankTimeSchedulerMock } from "../dank-time-scheduler/dank-time-scheduler-mock";
import { TelegramClientMock } from "../telegram-client/telegram-client-mock";
import { Util } from "../util/util";
import { BotCommand } from "./bot-command";
import { ChatRegistryMock } from "../../chat-registry/chat-registry-mock";
import { Chat } from "../../chat/chat";
import { DankTimeSchedulerMock } from "../../dank-time-scheduler/dank-time-scheduler-mock";
import { TelegramClientMock } from "../../telegram-client/telegram-client-mock";
import { Util } from "../../util/util";
import { BotCommand } from "../bot-command";
import { DankTimesBotCommands } from "./danktimesbot-commands";

describe("DankTimesBotCommands.addTime", () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { IChatRegistry } from "../chat-registry/i-chat-registry";
import { IDankTimeScheduler } from "../dank-time-scheduler/i-dank-time-scheduler";
import { DankTime } from "../dank-time/dank-time";
import { Release } from "../misc/release";
import { ITelegramClient } from "../telegram-client/i-telegram-client";
import { IUtil } from "../util/i-util";
import { IChatRegistry } from "../../chat-registry/i-chat-registry";
import { IDankTimeScheduler } from "../../dank-time-scheduler/i-dank-time-scheduler";
import { DankTime } from "../../dank-time/dank-time";
import { Release } from "../../misc/release";
import { ITelegramClient } from "../../telegram-client/i-telegram-client";
import { IUtil } from "../../util/i-util";
import { IDankTimesBotCommands } from "./i-danktimesbot-commands";

/** Holds functions that take a 'msg' and a 'match' parameter, and return string messages. */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Release } from "../misc/release";
import { Release } from "../../misc/release";

/** Holds functions that take a 'msg' and a 'match' parameter, and return string messages. */
export interface IDankTimesBotCommands {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { IChatRegistry } from "../chat-registry/i-chat-registry";
import { ITelegramClient } from "../telegram-client/i-telegram-client";
import { BotCommand } from "./bot-command";
import { IDankTimesBotCommands } from "./i-danktimesbot-commands";
import { IChatRegistry } from "../../chat-registry/i-chat-registry";
import { ITelegramClient } from "../../telegram-client/i-telegram-client";
import { BotCommand } from "../bot-command";
import { IDankTimesBotCommands } from "../commands/i-danktimesbot-commands";
import { IDankTimesBotCommandsRegistrar } from "./i-danktimesbot-commands-registrar";

export class DankTimesBotCommandsRegistrar implements IDankTimesBotCommandsRegistrar {
Expand All @@ -13,76 +13,76 @@ export class DankTimesBotCommandsRegistrar implements IDankTimesBotCommandsRegis
) { }

public async registerDankTimesBotCommands(): Promise<void> {
await this.telegramClient.retrieveBotName().then(() => {
await Promise.all([

this.telegramClient.registerCommand(new BotCommand("addtime",
"adds a dank time. format: [hour] [minute] [points] [text1] [text2] etc.",
this.dankTimesBotCommands, this.dankTimesBotCommands.addTime, true));
this.dankTimesBotCommands, this.dankTimesBotCommands.addTime, true)),

this.telegramClient.registerCommand(new BotCommand("danktimes", "shows the user-specified dank times",
this.dankTimesBotCommands, this.dankTimesBotCommands.dankTimes));
this.dankTimesBotCommands, this.dankTimesBotCommands.dankTimes)),

this.telegramClient.registerCommand(new BotCommand("help", "shows the available this.commands",
this.dankTimesBotCommands, this.dankTimesBotCommands.help));
this.dankTimesBotCommands, this.dankTimesBotCommands.help)),

this.telegramClient.registerCommand(new BotCommand("leaderboard", "shows the leaderboard",
this.dankTimesBotCommands, this.dankTimesBotCommands.leaderBoard));
this.dankTimesBotCommands, this.dankTimesBotCommands.leaderBoard)),

this.telegramClient.registerCommand(new BotCommand("releases", "shows the release log",
this.dankTimesBotCommands, this.dankTimesBotCommands.getReleaseLog));
this.dankTimesBotCommands, this.dankTimesBotCommands.getReleaseLog)),

this.telegramClient.registerCommand(new BotCommand("removetime", "removes a dank time. format: [hour] [minute]",
this.dankTimesBotCommands, this.dankTimesBotCommands.removeTime, true));
this.dankTimesBotCommands, this.dankTimesBotCommands.removeTime, true)),

this.telegramClient.registerCommand(new BotCommand("reset", "resets the scores",
this.dankTimesBotCommands, this.dankTimesBotCommands.resetChat, true, true));
this.dankTimesBotCommands, this.dankTimesBotCommands.resetChat, true, true)),

this.telegramClient.registerCommand(new BotCommand("setdailyrandomfrequency",
"sets the number of random dank times per day. format: [number]",
this.dankTimesBotCommands, this.dankTimesBotCommands.setDailyRandomTimes, true));
this.dankTimesBotCommands, this.dankTimesBotCommands.setDailyRandomTimes, true)),

this.telegramClient.registerCommand(new BotCommand("setdailyrandompoints",
"sets the points for random daily dank times. format: [number]",
this.dankTimesBotCommands, this.dankTimesBotCommands.setDailyRandomTimesPoints, true));
this.dankTimesBotCommands, this.dankTimesBotCommands.setDailyRandomTimesPoints, true)),

this.telegramClient.registerCommand(new BotCommand("setmultiplier",
"sets the multiplier for the score of the first user to score. format: [number]",
this.dankTimesBotCommands, this.dankTimesBotCommands.setMultiplier, true));
this.dankTimesBotCommands, this.dankTimesBotCommands.setMultiplier, true)),

this.telegramClient.registerCommand(new BotCommand("settimezone", "sets the time zone. format: [timezone]",
this.dankTimesBotCommands, this.dankTimesBotCommands.setTimezone, true));
this.dankTimesBotCommands, this.dankTimesBotCommands.setTimezone, true)),

this.telegramClient.registerCommand(new BotCommand("settings", "shows the current settings",
this.dankTimesBotCommands, this.dankTimesBotCommands.chatSettings));
this.dankTimesBotCommands, this.dankTimesBotCommands.chatSettings)),

this.telegramClient.registerCommand(new BotCommand("start", "starts keeping track of scores and sending messages",
this.dankTimesBotCommands, this.dankTimesBotCommands.startChat, true));
this.dankTimesBotCommands, this.dankTimesBotCommands.startChat, true)),

this.telegramClient.registerCommand(new BotCommand("stop", "stops keeping track of scores and sending messages",
this.dankTimesBotCommands, this.dankTimesBotCommands.stopChat, true));
this.dankTimesBotCommands, this.dankTimesBotCommands.stopChat, true)),

this.telegramClient.registerCommand(new BotCommand("toggleautoleaderboards",
"toggles whether a leaderboard is auto-posted 1 minute after every dank time",
this.dankTimesBotCommands, this.dankTimesBotCommands.toggleAutoLeaderboards, true));
this.dankTimesBotCommands, this.dankTimesBotCommands.toggleAutoLeaderboards, true)),

this.telegramClient.registerCommand(new BotCommand("toggledanktimenotifications",
"toggles whether notifications of normal dank times are sent",
this.dankTimesBotCommands, this.dankTimesBotCommands.toggleNotifications, true));
this.dankTimesBotCommands, this.dankTimesBotCommands.toggleNotifications, true)),

this.telegramClient.registerCommand(new BotCommand("togglefirstnotifications",
"toggles whether this chat announces the first user to score",
this.dankTimesBotCommands, this.dankTimesBotCommands.toggleFirstNotifications, true));
this.dankTimesBotCommands, this.dankTimesBotCommands.toggleFirstNotifications, true)),

this.telegramClient.registerCommand(new BotCommand("togglehandicaps",
"toggles whether the users with the lowest scores earn more points",
this.dankTimesBotCommands, this.dankTimesBotCommands.toggleHandicaps, true));
this.dankTimesBotCommands, this.dankTimesBotCommands.toggleHandicaps, true)),

this.telegramClient.registerCommand(new BotCommand("togglehardcoremode",
"toggles whether every day, users are punished if they haven't scored the previous day",
this.dankTimesBotCommands, this.dankTimesBotCommands.toggleHardcoreMode, true));
this.dankTimesBotCommands, this.dankTimesBotCommands.toggleHardcoreMode, true)),
]);

this.telegramClient.setOnAnyText((msg) => this.onAnyText(msg));
});
this.telegramClient.setOnAnyText((msg) => this.onAnyText(msg));
}

private onAnyText(msg: any): string {
Expand Down
79 changes: 79 additions & 0 deletions src/chat/chat.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,38 @@ describe("Chat.hardcoreModeCheck", () => {
// Assert
assert.equal(user.score, 0);
});

it("should NOT punish or otherwise alter a player's score if their score is 0", () => {

// Arrange
const user = new User(0, "user0", 0, nowMinus24Hours, false, 0);
const users = new Map<number, User>();
users.set(user.id, user);
const chat = new Chat(
moment, util, 0, "Europe/Amsterdam", true, 0, 10, 0, 0, users, [], [], false, 2, false, false, true);

// Act
chat.hardcoreModeCheck(now);

// Assert
assert.equal(user.score, 0);
});

it("should NOT punish or otherwise alter a player's score if their score is < 0", () => {

// Arrange
const user = new User(0, "user0", -10, nowMinus24Hours, false, 0);
const users = new Map<number, User>();
users.set(user.id, user);
const chat = new Chat(
moment, util, 0, "Europe/Amsterdam", true, 0, 10, 0, 0, users, [], [], false, 2, false, false, true);

// Act
chat.hardcoreModeCheck(now);

// Assert
assert.equal(user.score, -10);
});
});

describe("Chat.generateRandomDankTimes", () => {
Expand Down Expand Up @@ -278,4 +310,51 @@ describe("Chat.processMessage", () => {
assert.equal(scorer.score, 10);
});

it("should NOT award handicap value if user that scores deserves it and was first but is only one in chat", () => {

// Arrange
chat.removeUser(1);
chat.removeUser(2);
chat.removeUser(3);

// Act
const res = chat.processMessage(0, "user#0", "0113", now.unix());

// Assert
assert.equal(res, "👏 user#0 was the first to score!");
const sortedUsers = chat.sortedUsers();

const scorer = sortedUsers[0];
assert.equal(scorer.id, 0);
assert.equal(scorer.score, 10);
});

});

describe("Chat.removeUsersWithZeroScore", () => {

let chat: Chat;

beforeEach("Instantiate test variables", () => {
chat = new Chat(momentMock, util, 0);

for (let i = 0; i < 4; i++) {
const user = new User(i, `user#${i}`, i * 10);
chat.addUser(user);
}
});

it("should remove users with score of 0", () => {

// Act
chat.removeUsersWithZeroScore();

// Assert
const users = chat.sortedUsers();
assert.equal(users.length, 3);

for (const user of users) {
assert.notEqual(user.id, 0);
}
});
});
12 changes: 10 additions & 2 deletions src/chat/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ export class Chat {
if (this.hardcoreMode) {
const day = 24 * 60 * 60;
this.users.forEach((user) => {
if (timestamp - user.lastScoreTimestamp >= day) {
if (timestamp - user.lastScoreTimestamp >= day && user.score > 0) {
let punishBy = Math.round(user.score * punishByFraction);
punishBy = Math.max(punishBy, punishByPoints);

Expand All @@ -397,6 +397,14 @@ export class Chat {
}
}

public removeUsersWithZeroScore(): void {
this.users.forEach((user, id) => {
if (user.score === 0) {
this.users.delete(id);
}
});
}

/**
* Gets both normal and random dank times that have the specified text.
*/
Expand Down Expand Up @@ -425,7 +433,7 @@ export class Chat {
}

private userDeservesHandicapBonus(userId: number) {
if (!this.handicaps) {
if (!this.handicaps || this.users.size < 2) {
return false;
}
const sortedUsers = this.sortedUsers();
Expand Down
7 changes: 4 additions & 3 deletions src/context-root.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@ import * as momentImport from "moment-timezone";
import nodeCleanupImport = require("node-cleanup");
import TelegramBot = require("node-telegram-bot-api");

import { DankTimesBotCommands } from "./bot-commands/danktimesbot-commands";
import { DankTimesBotCommandsRegistrar } from "./bot-commands/danktimesbot-commands-registrar";
import { DankTimesBotCommands } from "./bot-commands/commands/danktimesbot-commands";
import { DankTimesBotCommandsRegistrar } from "./bot-commands/registrar/danktimesbot-commands-registrar";
import { ChatRegistry } from "./chat-registry/chat-registry";
import { DankTimeScheduler } from "./dank-time-scheduler/dank-time-scheduler";
import { TelegramClient } from "./telegram-client/telegram-client";
import { FileIO } from "./util/file-io/file-io";
import { Util } from "./util/util";

// tslint:disable-next-line:no-var-requires
export const version = require("../package.json").version;
export const fileIO = new FileIO(fs);

const initialChats = fileIO.loadChatsFromFile();
const util = new Util();
const version = "1.4.0";

export const chatRegistry = new ChatRegistry(momentImport, util);
chatRegistry.loadFromJSON(initialChats);
Expand Down
1 change: 1 addition & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const server = new Server(
contextRoot.moment,
contextRoot.cronJob,
contextRoot.dankTimesBotCommandsRegistrar,
contextRoot.version,
);

server.run();
27 changes: 27 additions & 0 deletions src/misc/node-telegram-bot-api-mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export async function getMe() {
return {
username: "botusername",
};
}

export async function getChatAdministrators(chatId: number) {
return [
{
user: {
id: 0,
},
},
];
}

export async function sendMessage(chatId: number, htmlMessage: string, options: any) {
/**/
}

export function onText(regexp: RegExp, callback: ((msg: any, match: RegExpExecArray | null) => void)): void {
/**/
}

export function on(event: string, callback: ((msg: any, match: RegExpExecArray | null) => void)): void {
/**/
}
Loading

0 comments on commit a0bea40

Please sign in to comment.