Skip to content

Commit

Permalink
Add decrease rep with user mention (#93)
Browse files Browse the repository at this point in the history
* Add decrease rep with user mention

* remove test

Co-authored-by: Ahmad Syafiq <[email protected]>
  • Loading branch information
ahmadsyafiqruhazat and Ahmad Syafiq authored Oct 27, 2021
1 parent 1800b9b commit a712d1e
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 33 deletions.
104 changes: 104 additions & 0 deletions src/bots/Reputation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,78 @@ describe('ReputationBot', () => {
assertBotSaid(messages, /.*?/);
await assert(triggerMessage);
});

// Testing when user is mention
it('when user mentions another user with "boo"', async () => {
await createUserInDb();
const triggerMessage = createTgTextMessage('@omar_alfaruq boo', {
chat: thisChat,
from: senderUser,
entities: [
{
type: 'mention',
offset: 0,
length: 13,
},
],
});

const messages = await runBot([ScriberBot, ReputationBot], ({ sendMessage }) => {
sendMessage(mainMessage);
sendMessage(triggerMessage);
});

assertBotSaid(messages, /decreased reputation/);
await assert({
...triggerMessage,
reply_to_message: {
from: {
id: 2,
username: 'omar_alfaruq',
},
},
});
});

// Testing when user is mention (text_mention -> when user has no username)
// https://core.telegram.org/bots/api#messageentity
it('when user mentions another user with "boo"', async () => {
await createUserInDb();
const triggerMessage = createTgTextMessage('@omar_alfaruq boo', {
chat: thisChat,
from: senderUser,
entities: [
{
type: 'text_mention',
offset: 0,
length: 13,
user: {
id: 2,
is_bot: false,
first_name: 'Omar',
last_name: 'Al-Faruq',
username: 'omar_alfaruq',
},
},
],
});

const messages = await runBot([ScriberBot, ReputationBot], ({ sendMessage }) => {
sendMessage(mainMessage);
sendMessage(triggerMessage);
});

assertBotSaid(messages, /decreased reputation/);
await assert({
...triggerMessage,
reply_to_message: {
from: {
id: 2,
username: 'omar_alfaruq',
},
},
});
});
});

describe('does not change reputation', () => {
Expand Down Expand Up @@ -809,6 +881,38 @@ describe('ReputationBot', () => {
assertBotSaid(messages, 'Tag only one user at a time to increase rep!');
await assert(0);
});

it('when user mentions multiple users with "boo"', async () => {
const mainMessage = createTgTextMessage('Is it your new PC?', {
chat: thisChat,
from: recipientUser,
reply_to_message: undefined,
});
const triggerMessage = createTgTextMessage('@omar_alfaruq @abu_bakr boo', {
chat: thisChat,
from: senderUser,
entities: [
{
type: 'mention',
offset: 0,
length: 13,
},
{
type: 'mention',
offset: 0,
length: 9,
},
],
});

const messages = await runBot([ScriberBot, ReputationBot], ({ sendMessage }) => {
sendMessage(mainMessage);
sendMessage(triggerMessage);
});

assertBotSaid(messages, 'Tag only one user at a time to increase rep!');
await assert(0);
});
});
});

Expand Down
99 changes: 66 additions & 33 deletions src/bots/Reputation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { MsocietyBotContext } from '../context';

const bot = new Composer<MsocietyBotContext>();

async function vote(ctx: MsocietyBotContext, sender: TelegramUser, recipient: TelegramUser) {
async function upvote(ctx: MsocietyBotContext, sender: TelegramUser, recipient: TelegramUser) {
const canVote = await Reputation.isAllowedToVote(ctx.entityManager, sender);

// Can't vote for yourself :)
Expand Down Expand Up @@ -49,11 +49,45 @@ async function vote(ctx: MsocietyBotContext, sender: TelegramUser, recipient: Te
}
}

async function downvote(ctx: MsocietyBotContext, sender: TelegramUser, recipient: TelegramUser) {
const canVote = await Reputation.isAllowedToVote(ctx.entityManager, sender);

// Can't vote for yourself :)
if (recipient.id === sender.id) {
await ctx.replyWithMarkdown('Are you _ok_?', { reply_to_message_id: ctx.message.message_id });
}
// Can't vote for the bot.
else if (recipient.id === ctx.botInfo.id) {
// eslint-disable-next-line quotes
await ctx.reply('🙂 Excuse me?', {
reply_to_message_id: ctx.message.message_id,
});
}
// Does user have enough votes in their quota to give out?
else if (!canVote) {
const { nextVote } = await Reputation.getVoteQuota(ctx.entityManager, ctx.message.from);

await ctx.replyWithMarkdown(
`You have already used up your vote quota of ${voteQuota} for the past ${voteQuotaDuration} hours. Please try again later!\nYou will receive a new vote in *${nextVote.hours} hours* and *${nextVote.minutes} minutes*`,
{ reply_to_message_id: ctx.message.message_id },
);
}
// Can't vote for bots
else if (!recipient.is_bot && canVote) {
await insertReputation(ctx.entityManager, sender, recipient, ctx.chat, ctx.message, defaultVoteValue * -1);
const senderRep = await Reputation.getLocalReputation(ctx.entityManager, sender, ctx.chat);
const recipientRep = await Reputation.getLocalReputation(ctx.entityManager, recipient, ctx.chat);
await ctx.replyWithMarkdown(
`*${sender.first_name}* (${senderRep}) has decreased reputation of *${recipient.first_name}* (${recipientRep})`,
{ reply_to_message_id: ctx.message.message_id },
);
}
}
bot.hears(/thank you|thanks|👍|💯|👆|🆙|🔥/i, async ctx => {
const mentionEntities =
ctx.message?.entities?.filter(entity => ['mention', 'text_mention'].includes(entity.type)) || [];
if (ctx.message.reply_to_message !== undefined) {
await vote(ctx, ctx.from, ctx.message.reply_to_message.from);
await upvote(ctx, ctx.from, ctx.message.reply_to_message.from);
} else if (
// check if there is a mention
mentionEntities.length
Expand All @@ -80,48 +114,47 @@ bot.hears(/thank you|thanks|👍|💯|👆|🆙|🔥/i, async ctx => {
return;
}
const recipient = await ctx.getChatMember(+recipientId);
await vote(ctx, ctx.message.from, recipient.user);
await upvote(ctx, ctx.message.from, recipient.user);
} else if (entity.type === 'text_mention') {
await vote(ctx, ctx.message.from, entity.user);
await upvote(ctx, ctx.message.from, entity.user);
}
}
});

bot.hears(/👎|👇|🔽|\bboo(o*)\b|\beww(w*)\b/i, async ctx => {
const mentionEntities =
ctx.message?.entities?.filter(entity => ['mention', 'text_mention'].includes(entity.type)) || [];
if (ctx.message.reply_to_message !== undefined) {
const sender = ctx.message.from;
const recipient = ctx.message.reply_to_message.from;
const canVote = await Reputation.isAllowedToVote(ctx.entityManager, sender);

// Can't vote for yourself :)
if (recipient.id === sender.id) {
await ctx.replyWithMarkdown('Are you _ok_?', { reply_to_message_id: ctx.message.message_id });
}
// Can't vote for the bot.
else if (recipient.id === ctx.botInfo.id) {
// eslint-disable-next-line quotes
await ctx.reply('🙂 Excuse me?', {
await downvote(ctx, ctx.from, ctx.message.reply_to_message.from);
} else if (
// check if there is a mention
mentionEntities.length
) {
if (mentionEntities.length > 1) {
await ctx.reply('Tag only one user at a time to increase rep!', {
reply_to_message_id: ctx.message.message_id,
});
return;
}
// Does user have enough votes in their quota to give out?
else if (!canVote) {
const { nextVote } = await Reputation.getVoteQuota(ctx.entityManager, ctx.message.from);
// get the mention metadata
const entity = mentionEntities[0];

await ctx.replyWithMarkdown(
`You have already used up your vote quota of ${voteQuota} for the past ${voteQuotaDuration} hours. Please try again later!\nYou will receive a new vote in *${nextVote.hours} hours* and *${nextVote.minutes} minutes*`,
{ reply_to_message_id: ctx.message.message_id },
);
}
// Can't vote for bots
else if (!recipient.is_bot && canVote) {
await insertReputation(ctx.entityManager, sender, recipient, ctx.chat, ctx.message, defaultVoteValue * -1);
const senderRep = await Reputation.getLocalReputation(ctx.entityManager, sender, ctx.chat);
const recipientRep = await Reputation.getLocalReputation(ctx.entityManager, recipient, ctx.chat);
await ctx.replyWithMarkdown(
`*${sender.first_name}* (${senderRep}) has decreased reputation of *${recipient.first_name}* (${recipientRep})`,
{ reply_to_message_id: ctx.message.message_id },
);
if (entity.type === 'mention') {
//get username from text using metadata
const username = ctx.message.text.substr(entity.offset + 1, entity.length - 1);
// telegram api doesn't provide resolving user by username so we depend on our db to get userID
const recipientId = (await User.getUserByUsername(ctx.entityManager, username))?.id;
if (!recipientId) {
// eslint-disable-next-line quotes
await ctx.reply("Can't find user in DB. Did they change their username?", {
reply_to_message_id: ctx.message.message_id,
});
return;
}
const recipient = await ctx.getChatMember(+recipientId);
await downvote(ctx, ctx.message.from, recipient.user);
} else if (entity.type === 'text_mention') {
await downvote(ctx, ctx.message.from, entity.user);
}
}
});
Expand Down

0 comments on commit a712d1e

Please sign in to comment.