Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/contact sales #10

Merged
merged 6 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 0 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@

Intenteded to display real estate properties concisely via a Telegram Bot


[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=QuantGeekDev_PropertyGram-telegram-bot&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=QuantGeekDev_PropertyGram-telegram-bot)


## Features

- Built with TypeScript for static typing and enhanced code quality.
Expand All @@ -14,50 +12,10 @@ Intenteded to display real estate properties concisely via a Telegram Bot
- Easy-to-use script commands for compiling, starting, and managing the bot process.
- Prettier integrated for code formatting.

## Usage

After cloning the repository, you can use the following npm scripts:


- `compile`: Compiles the TypeScript files to JavaScript, placing the compiled files in the `dist` directory.
- `postcompile`: Copies the locales from the `src` directory to the `dist` directory.
- `bg:start`: Prepares the environment and starts the bot in the background using pm2.
- `bg:restart`: Restarts the bot service.
- `bg:logs`: Fetches logs for the bot, defaulting to the last 1000 lines.
- `start`: Compiles the TypeScript files and starts the bot.
- `lint`: Formats the code using Prettier.

## Installation

To use this project:

1. Ensure you have Node.js (version 4 or higher) and npm (version 2 or higher) installed.
2. Clone the repository.
3. Run `npm install` to install all the dependencies and devDependencies listed.

## Dependencies

- `@grammyjs/i18n`: For internationalization support.
- `dotenv`: To manage environment variables.
- `grammy`: The framework used to create the bot.
- `mongodb`: To interact with MongoDB databases.

## DevDependencies

Includes various types, ESLint configurations, Prettier, and TypeScript for linting, formatting, and compiling the code.

## Configuration

Modify the `.env` file to include your bot tokens and any other environment-specific configurations. Additionally, tailor the `src/locales` as needed for internationalization.

## License

This project is licensed under the GPL-3.0-or-later. Please ensure you comply with the license terms while using or modifying the template.

## Contributions

Contributions are welcome. Please fork the repository, make your changes, and submit a pull request.

---

This README provides a basic outline of the ts-tg-bot package. You can expand each section with more detailed information about configuration, usage, and development practices as needed for your particular bot implementation.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
"bg:restart": "npm run prepare && pm2 restart propertygram-bot",
"bg:logs": "pm2 logs telegram-bot --lines 1000 -f",
"start": "npm run compile && node .",
"start:dev": " node --watch . ",
"build:dev": "tsc -watch",
"lint": "npx prettier --write src",
"prepare": "husky install"
},
Expand Down
2 changes: 1 addition & 1 deletion src/config/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export async function startApp() {
debug("Starting app...");
try {
loadEnv();
validateEnv(["TELEGRAM_TOKEN", "DB_CONNECTION_STRING"]);
validateEnv(["TELEGRAM_TOKEN", "DB_CONNECTION_STRING", "ADMIN_GROUP_ID"]);
} catch (error) {
console.error("Error occurred while loading environment:", error);
process.exit(1);
Expand Down
11 changes: 7 additions & 4 deletions src/config/bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ import type { I18n } from "@grammyjs/i18n/dist/source/i18n.js";
import { Bot as TelegramBot, session } from "grammy";

import { resolvePath } from "../helpers/resolve-path.js";
import { createReplyWithTextFunc } from "../services/context.js";
import { createReplyWithTextFunc } from "../services/context.service.js";
import type { CustomContext } from "../types/context.js";
import type { Chat, Database } from "../types/database.js";
import { initLocaleEngine } from "./locale-engine.js";
import { startController } from "../controllers/start.js";
import { stopController } from "../controllers/stop.js";
import type { Bot } from "../types/telegram.js";
import { buildName, getOrCreatePlayer } from "../services/user.js";
import { getOrCreateChat } from "../services/chat.js";
import { buildName, getOrCreatePlayer } from "../services/user.service.js";
import { getOrCreateChat } from "../services/chat.service.js";
import { propertiesController } from "../controllers/properties.js";
import { fileIdController } from "../controllers/fileId.js";
import { contactSalesController } from "../controllers/contactSales.js";

function extendContext(bot: Bot, database: Database) {
bot.use(async (ctx, next) => {
Expand All @@ -38,7 +39,8 @@ function extendContext(bot: Bot, database: Database) {
userId: ctx.from.id,
name: buildName(ctx.from.first_name, ctx.from.last_name)
}),
chat
chat,
property: null
};

await next();
Expand All @@ -56,6 +58,7 @@ function setupControllers(bot: Bot) {
bot.use(stopController);
bot.use(propertiesController);
bot.use(fileIdController);
bot.use(contactSalesController);
}

export async function startBot(database: Database) {
Expand Down
12 changes: 12 additions & 0 deletions src/controllers/contactSales.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Composer } from "grammy";
import type { CustomContext } from "../types/context.js";
import { notifySalesTeam } from "../services/Admin/notifySalesTeam.js";

export const contactSalesController = new Composer<CustomContext>();
contactSalesController.callbackQuery("contact-sales", async ctx => {
ctx.answerCallbackQuery("");
ctx.reply(
"Your request has been registered - an agent will contact you shortly"
);
notifySalesTeam(ctx);
});
12 changes: 8 additions & 4 deletions src/controllers/start.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { Composer } from "grammy";
import type { CustomContext } from "../types/context.js";
import { startMenu } from "../menus/startMenu.js";

export const startController = new Composer<CustomContext>();
startController.command("start", async ctx => {
await ctx.text("start", {
name: ctx.config.user.name,
chatName: ctx.config.chat?.title ?? "PM"
});
const salisolLogoUrl =
"https://lh3.googleusercontent.com/u/0/drive-viewer/AEYmBYSo6VRezOEbJpP0wzkLbT9JQ_f_HbNJw_MgzN45az99ZU5qvOe3Ad5N7qWGlHg_5iIUrRO-2sb82LOgcd-cOuBt8vNLSg=w2560-h1204";
await ctx.replyWithPhoto(salisolLogoUrl);
await ctx.reply(
`Hello ${ctx.config.user.name}, welcome to SaliSol☀️🏠 - 30 years developing properties on Spain's Costa Blanca.\nHow can we help you?`,
{ reply_markup: startMenu }
);
});
1 change: 1 addition & 0 deletions src/environment.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export declare global {
interface ProcessEnv {
TELEGRAM_TOKEN: string;
DB_CONNECTION_STRING: string;
ADMIN_GROUP_ID: string;
}
}
}
20 changes: 11 additions & 9 deletions src/menus/propertyMenu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ import { InlineKeyboard } from "grammy";

export const fullPropertyControlKeyboard = new InlineKeyboard()
.text("« Previous Property", "previous-property")
.text("Next Property » ", "next-property");
.text("Next Property » ", "next-property")
.row()
.text("Contact me about this property", "contact-sales");

export const nextPropertyControlKeyboard = new InlineKeyboard().text(
"Next Property » ",
"next-property"
);
export const nextPropertyControlKeyboard = new InlineKeyboard()
.text("Next Property » ", "next-property")
.row()
.text("Contact me about this property", "contact-sales");

export const previousPropertyControlKeyboard = new InlineKeyboard().text(
"« Previous Property",
"previous-property"
);
export const previousPropertyControlKeyboard = new InlineKeyboard()
.text("« Previous Property", "previous-property")
.row()
.text("Contact me about this property", "contact-sales");
10 changes: 10 additions & 0 deletions src/menus/startMenu.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { InlineKeyboard } from "grammy";

const salisolParkWebsiteUrl = "https://salisolpark.com/";

export const startMenu = new InlineKeyboard()
.text("🏠 View Developments", "view-developments")
.row()
.text("📞 Contact sales", "contact-sales")
.row()
.url("🌐 Visit website", salisolParkWebsiteUrl);
17 changes: 17 additions & 0 deletions src/services/Admin/notifySalesTeam.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { CustomContext } from "../../types/context";

export const notifySalesTeam = (ctx: CustomContext) => {
const adminGroupId = process.env.ADMIN_GROUP_ID;
const userId = ctx.config.user.userId;
const userName = ctx.config.user.name;
const propertyOfInterest = null;
const userClickable = `[${userName}](tg://user?id=${userId})`;

const formattedNotificationMessage = `A new client is requesting information:\nName: ${userName}\nUser: @${userClickable}\n${
propertyOfInterest ? `Interested in ${propertyOfInterest}` : ""
}`;

ctx.api.sendMessage(adminGroupId, formattedNotificationMessage, {
parse_mode: "MarkdownV2"
});
};
File renamed without changes.
File renamed without changes.
File renamed without changes.
3 changes: 2 additions & 1 deletion src/types/context.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Context, SessionFlavor } from "grammy";
import type { I18nContextFlavor, TemplateData } from "@grammyjs/i18n";
import type { Extra } from "./telegram.js";
import type { Chat, Database, User } from "./database.js";
import type { Chat, Database, Property, User } from "./database.js";

export interface Custom<C extends Context> {
text: (
Expand All @@ -13,6 +13,7 @@ export interface Custom<C extends Context> {
config: {
user: User;
chat: Chat | null;
property: Property | null;
};

db: Database;
Expand Down
Loading