Skip to content

Commit

Permalink
Migrate to grammY
Browse files Browse the repository at this point in the history
  • Loading branch information
rojvv committed May 12, 2021
1 parent 07d922f commit 1e29c51
Show file tree
Hide file tree
Showing 18 changed files with 184 additions and 164 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ This bot needs a Linux system, Node JS version 15 or newer with the packages spe
### Heroku

[![Deploy to Heroku](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/callsmusic/callsmusic2)

- You can generate a string session [here](https://rojserbest.github.io/bssg).

## Commands
Expand Down
39 changes: 39 additions & 0 deletions bot/handlers/controls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const { Composer } = require("grammy");
const connections = require("../../connections");
const queues = require("../../queues");

const composer = new Composer();

composer.command("resume", async (ctx) => {
const result = connections.resume(ctx.chat.id);
if (result == 0) await ctx.reply("<b>▶️ Resumed</b>");
else if (result === 1) await ctx.reply("<b>❌ Not playing</b>");
else if (result === 2) await ctx.reply("<b>❌ Not in call</b>");
});

composer.command("pause", async (ctx) => {
const result = connections.pause(ctx.chat.id);
if (result == 0) await ctx.reply("<b>⏸ Paused</b>");
else if (result === 1) await ctx.reply("<b>❌ Not playing</b>");
else if (result === 2) await ctx.reply("<b>❌ Not in call</b>");
});

composer.command("skip", async (ctx) => {
const result = await connections.stop(ctx.chat.id);
if (result === 0) await ctx.reply("<b>⏩ Skipped</b>");
else if (result === 1) await ctx.reply("<b>❌ Not playing</b>");
else if (result === 2) await ctx.reply("<b>❌ Not in call</b>");
});

composer.command("stop", async (ctx) => {
if (connections.inCall(ctx.chat.id)) {
await connections.stop(ctx.chat.id);
connections.remove(ctx.chat.id);
queues.clear(ctx.chat.id);
await ctx.reply("<b>⏹ Stopped</b>");
} else {
await ctx.reply("<b>❌ Not in call</b>");
}
});

module.exports = composer;
7 changes: 0 additions & 7 deletions bot/handlers/errors.js

This file was deleted.

36 changes: 22 additions & 14 deletions bot/handlers/index.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
module.exports = (app) => {
require("fs").readdir(__dirname, (err, files) => {
if (err) {
console.log(err);
process.exit();
} else {
for (var file in files) {
if (files[file].endsWith("js")) {
file = files[file].slice(0, files[file].length - 3);
if (file != "index") {
app.use(require(`./${file}`));
}
const play = require("./play");
const controls = require("./controls");
const voice_chat_ended = require("./voice_chat_ended");
const private = require("./private");

module.exports = (bot) => {
bot
.filter((ctx) => {
if (ctx.chat && ctx.chat.type == "supergroup") {
if (
ctx.message &&
ctx.message.reply_to_message &&
(ctx.message.reply_to_message.audio ||
ctx.message.reply_to_message.voice)
) {
return true;
}
}
}
});
return false;
})
.use(play);
bot.filter((ctx) => ctx.chat?.type == "supergroup", controls);
bot.filter((ctx) => ctx.chat?.type == "private", private);
bot.use(voice_chat_ended);
};
15 changes: 0 additions & 15 deletions bot/handlers/pause.js

This file was deleted.

90 changes: 40 additions & 50 deletions bot/handlers/play.js
Original file line number Diff line number Diff line change
@@ -1,58 +1,48 @@
const { Composer } = require("telegraf");
const { Composer, InputFile } = require("grammy");
const { escape } = require("html-escaper");
const ffmpeg = require("../../ffmpeg");
const connections = require("../../connections");
const queues = require("../../queues");
const { createImage } = require("../../image");
const { esc, link } = require("../helpers");
const { link, getFile } = require("../helpers");

module.exports = Composer.command("play", async (ctx) => {
if (ctx.chat.type != "supergroup") {
await ctx.reply("This command is for groups!");
} else if (
ctx.message.reply_to_message &&
(ctx.message.reply_to_message.audio || ctx.message.reply_to_message.voice)
) {
const file =
ctx.message.reply_to_message.audio ||
ctx.message.reply_to_message.voice,
fileIsVoice = typeof ctx.message.reply_to_message.voice !== "undefined",
input = (await ctx.telegram.getFileLink(file.file_id)).href,
text1 = fileIsVoice ? "Voice" : file.title,
text2 = fileIsVoice ? ctx.from.first_name : file.performer,
image = await createImage("audio", { text1: text1, text2: text2 });
const readable = ffmpeg(input);
if (connections.playing(ctx.chat.id)) {
const position = queues.push(ctx.chat.id, {
title: text1,
artist: text2,
readable: readable,
});
await ctx.replyWithPhoto(
{ source: image },
{
caption: `<b><a href="tg://user?id=${ctx.from.id}">${esc(
ctx.from.first_name
)}</> queued <a href="${link(ctx.message)}">${
fileIsVoice ? "a voice message" : esc(text2 + " - " + text1)
}</> at position ${position}...</>`,
parse_mode: "html",
}
);
} else {
await connections.setReadable(ctx.chat.id, readable);
await ctx.replyWithPhoto(
{ source: image },
{
caption: `<b><a href="tg://user?id${ctx.from.id}">${esc(
ctx.from.first_name
)}</> is now playing <a href="${link(ctx.message)}">${
fileIsVoice ? "a voice message" : esc(text2) + " - " + esc(text1)
}</></>...`,
parse_mode: "html",
}
);
}
const composer = new Composer();

composer.command("play", async (ctx) => {
const file =
ctx.message.reply_to_message.audio || ctx.message.reply_to_message.voice,
fileIsVoice = typeof ctx.message.reply_to_message.voice !== "undefined",
input = await getFile(ctx, file.file_id),
text1 = fileIsVoice ? "Voice" : file.title,
text2 = fileIsVoice ? ctx.from.first_name : file.performer,
image = await createImage("audio", { text1: text1, text2: text2 });
const readable = ffmpeg(input);

if (connections.playing(ctx.chat.id)) {
const position = queues.push(ctx.chat.id, {
title: text1,
artist: text2,
readable: readable,
});

await ctx.replyWithPhoto(new InputFile(image), {
caption: `#️⃣ <b><a href="tg://user?id=${ctx.from.id}">${escape(
ctx.from.first_name
)}</> queued <a href="${link(ctx.message)}">${
fileIsVoice ? "a voice message" : escape(text2 + " - " + text1)
}</> at position ${position}...</>`,
});
} else {
await ctx.reply("Reply to an audio file or voice message!");
await connections.setReadable(ctx.chat.id, readable);

await ctx.replyWithPhoto(new InputFile(image), {
caption: `▶️ <b><a href="tg://user?id${ctx.from.id}">${escape(
ctx.from.first_name
)}</> is now playing <a href="${link(ctx.message)}">${
fileIsVoice ? "a voice message" : escape(text2) + " - " + escape(text1)
}</></>...`,
});
}
});

module.exports = composer;
27 changes: 27 additions & 0 deletions bot/handlers/private.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const { Composer, InlineKeyboard } = require("grammy");
const { escape } = require("html-escaper");

const composer = new Composer();

composer.command("start", async (ctx) => {
await ctx.reply(
`<b>👋🏻 Hi ${escape(ctx.from.first_name)}!</b>
I am Calls Music bot, I let you play music in group calls.
The commands I currently support are:
/play - play the replied audio file or YouTube video
/pause - pause the audio stream
/resume - resume the audio stream
/skip - skip the current audio stream
/stop - clear the queue and remove the userbot from the call`,
{
reply_markup: new InlineKeyboard()
.url("🔈 Channel", "https://t.me/callsmusic")
.url("Group 💬", "https://t.me/callsmusicchat"),
}
);
});

module.exports = composer;
13 changes: 0 additions & 13 deletions bot/handlers/resume.js

This file was deleted.

14 changes: 0 additions & 14 deletions bot/handlers/skip.js

This file was deleted.

5 changes: 0 additions & 5 deletions bot/handlers/start.js

This file was deleted.

15 changes: 0 additions & 15 deletions bot/handlers/stop.js

This file was deleted.

8 changes: 6 additions & 2 deletions bot/handlers/voice_chat_ended.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
const { Composer } = require("telegraf");
const { Composer } = require("grammy");
const connections = require("../../connections");
const queues = require("../../queues");

module.exports = Composer.on("voice_chat_ended", async (ctx) => {
const composer = new Composer();

composer.on(":voice_chat_ended", async (ctx) => {
connections.remove(ctx.chat.id);
queues.clear(ctx.chat.id);
});

module.exports = composer;
14 changes: 7 additions & 7 deletions bot/helpers.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
module.exports.esc = (str) => {
return str
.replace(/&/g, "&amp;")
.replace(/"/g, "&quot;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;");
};
const config = require("../config");

module.exports.link = (msg) => {
let chatId = msg.chat.id.toString();
if (chatId.startsWith("-100")) chatId = chatId.slice(3, chatId.length);
return `https://t.me/c/${chatId}/${msg.reply_to_message.message_id}`;
};

module.exports.getFile = async (ctx, fileId) => {
return `https://api.telegram.org/file/bot${config.botToken}/${
(await ctx.api.getFile(fileId)).file_path
}`;
};
19 changes: 16 additions & 3 deletions bot/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
const { Telegraf } = require("telegraf");
const { Bot } = require("grammy");
const config = require("../config");

const bot = new Telegraf(config.botToken);
const bot = new Bot(config.botToken);
require("./handlers")(bot);

bot.api.config.use((prev, method, payload) => {
return prev(method, {
...payload,
parse_mode: "HTML",
});
});

bot.catch(async (error) => {
if (error.error instanceof Error) {
await error.ctx.reply(error.error.toString());
}
});

module.exports.bot = bot;
module.exports.start = async () => {
await bot.launch({ dropPendingUpdates: true });
await bot.start({ dropPendingUpdates: true });
};
Loading

0 comments on commit 1e29c51

Please sign in to comment.