Skip to content

Commit

Permalink
Merge pull request #7 from QuantGeekDev/feature/properties
Browse files Browse the repository at this point in the history
Feature/properties
  • Loading branch information
QuantGeekDev authored Jan 5, 2024
2 parents 59f5456 + 2418f61 commit 289e974
Show file tree
Hide file tree
Showing 23 changed files with 226 additions and 112 deletions.
2 changes: 1 addition & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
],
"rules": {
"@typescript-eslint/consistent-type-imports": "error",
"quotes": [2, "single", { "avoidEscape": true }],
"quotes": [2, "double", { "avoidEscape": true }],
"no-extra-parens": "off",
"arrow-parens": "off",
"prettier/prettier": 2,
Expand Down
2 changes: 0 additions & 2 deletions .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
"trailingComma": "none",
"tabWidth": 2,
"semi": true,
"singleQuote": true,
"useTabs": true,
"jsxSingleQuote": true,
"bracketSpacing": true,
"arrowParens": "avoid"
}
68 changes: 34 additions & 34 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"scripts": {
"compile": "tsc",
"postcompile": "cp -r src/locales dist",
"bg:start": "npm run prepare && pm2 start dist/index.js --name propertygram-bot",
"bg:restart": "npm run prepare && pm2 restart telegram-bot",
"bg:start": "npm run prepare && pm2 start dist/index.js --name propertygram-bot -f",
"bg:restart": "npm run prepare && pm2 restart propertygram-bot",
"bg:logs": "pm2 logs telegram-bot --lines 1000 -f",
"start": "npm run compile && node .",
"lint": "npx prettier --write src",
Expand Down
20 changes: 20 additions & 0 deletions propertiesSampleData.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"collection": "SaliSol Hills",
"name": "Villa 6",
"price": 670000,
"availability": true,
"videoFileId": "https://www.dropbox.com/sh/t6330gcog0lz7dh/AADqYOkfEnvIQ0RF6Lr0eRBja?dl=0&preview=Video+1+SaliSol+Hills+Showhouse+2023.mp4",
"thumbnailUrl": "https://uc470239d7d0c1c41f915323d5c8.previews.dropboxusercontent.com/p/thumb/ACLJ7D6O6bqDe2gRpcdVMDPaxNwZYWAenzJD8IQuZKGoaWdojbcZHMHHw0X-6CUmisfriGocNXvxH1tLSty6kEh3PftuhgeMPVUlQuhD7KmGYWfmqnWQKPY9bwnKjU-qxJJv7c2StyA_xn6H4l4MCTF0dWVHalbKeTT5aW5ucsm5f6raAcqCXx7mRQto9AkM3lHzDi8dw7imp65me_EFKUmEziFK108IecRwKQ1KZdNWrjVIuAcaIyGzq51l--Kphv6rh9tHaSXx0DMv_MX0vtYbL751cve0h9YGrvGPnFUMKhP6oPqXAFzLnSJCc3qnbzfaGuaWeI7sjBLh5-MXtt8JTZfsU8-om8Kv1k0gtPF4dg/p.png",
"builtMetersSquared": 168,
"plotMetersSquared": 532,
"dropboxUrl": "https://www.dropbox.com/sh/t6330gcog0lz7dh/AADqYOkfEnvIQ0RF6Lr0eRBja?dl=0",
"telegramContactUrl": "https://t.me/PropertyGram_bot",
"websiteUrl": "https://salisolpark.com/salisol-hills",
"albumUrls": [
"https://uc470239d7d0c1c41f915323d5c8.previews.dropboxusercontent.com/p/thumb/ACLJ7D6O6bqDe2gRpcdVMDPaxNwZYWAenzJD8IQuZKGoaWdojbcZHMHHw0X-6CUmisfriGocNXvxH1tLSty6kEh3PftuhgeMPVUlQuhD7KmGYWfmqnWQKPY9bwnKjU-qxJJv7c2StyA_xn6H4l4MCTF0dWVHalbKeTT5aW5ucsm5f6raAcqCXx7mRQto9AkM3lHzDi8dw7imp65me_EFKUmEziFK108IecRwKQ1KZdNWrjVIuAcaIyGzq51l--Kphv6rh9tHaSXx0DMv_MX0vtYbL751cve0h9YGrvGPnFUMKhP6oPqXAFzLnSJCc3qnbzfaGuaWeI7sjBLh5-MXtt8JTZfsU8-om8Kv1k0gtPF4dg/p.png",
"https://ucd3b2b2169690f13f7943ad683e.previews.dropboxusercontent.com/p/thumb/ACK1cGb1225TlUB5zrve84aiZ03Wx-1D7ic-toemLMfr70PYmbUBZTH073DcYCAjm9GiO5PcOf_4zl7fRaasaRcQQpiTsvXvd6qjROClxeyZ9Z40yil08MzpFMz0IHtScRDg6cPA2ppVRD_DlNfPhFj-OfBc3MX3d5kJOQPZs9xnJWn5PrIhJ48dhAycsox1PuRe2pFV0p5-SfftP0VZjkDSr2Hd50R9n0s34J_boekj_cUy68YI4lmGBlpNpdW44e1fMoLDZmwuV1owDdSotaqGDxUD9U03isNh69FfVpinLzw9y34gcHozq0xZ-VextAtrtrt2bbaQMuJDI-N7t42qGYbMKOEA_uaZYekRDCeJAg/p.png",
"https://ucbda0eb239a53969d8a8e7f5475.previews.dropboxusercontent.com/p/thumb/ACLqnVpH6F7yEf4Nlojv_K5vcRsq2MF8n-mRdf5IUMXsv3_Y5poMtlbty1VBRyg214Wqsyh-JjFUv_6tk1h5pe8Dn3c6BwqydRNKYW9o4gO0aMzvq3G13DZ-y1hkPFifyAzYlG_ibSv0Xmrcwvv5kAzs9raGFhe7dMMLm0j4oVbThEgDVOcVRRkLyp0mQl825lH-v57ZP_J71izkP_Dxdi3hyUWxp2FuOq7ZtWGJuub5S7uBmxiSjenOzBe0PNthPGjoG5K3sJFr_KynvwRtYXummX8APLR5ezOWf2M8mNcXRcOI2nH7DcyzZIYgsVlsaxCs-oS2I89wAOLog_PcJB4eqGvmbBe5R0iW8bWQd0c6GA/p.jpeg",
"https://uc177e23be7b8c96b07f3e30647c.previews.dropboxusercontent.com/p/thumb/ACIFhDABAj7th24mAYq_nS0PzZSnryTlkBQL_74SBQf2mIFgbBsn-ZI_s-dLHAqtdkAJZxIGq0NZZ0XGeW2aRR9MN6OaJZ8xU5VLnFW_57kNtaOgasmmtl13Jg9SdFeu_SaEh2w2sDfqeieB4vJlapSkGqQaVZgv7p7uyNqf39g5gce2rnxvSCuTocQs52hpfWqlvXNT35XUb5Tw2f-wx6MZXFWX0cVPI5FxVAyPV2EDgFdE_rgSQ0vPaCENjJAix7WXajPI2Df8tCXntoSBEY8gDZYy4T7Maz_kjBSR5euIgKngdRLF2iHtLwgIbSfQyKxGxm2x3crjUJv8zmRCNRFVSxiJL_nJzySHumYgGxzO_g/p.jpeg",
"https://ucdc0769904db036def229337527.previews.dropboxusercontent.com/p/thumb/ACKJuGcDqfCB039AMybN4Lbog87xyqBblw-rnUyll17XVCZRHe-P-6r81amFKJEU-CX5hsgP4fJQo-9nl5OOqq3c_DN5xsPG2p4TKPvhmkDfzgNQ_ok78aroz4JaWsybLknnE3mbr7Yc2jbx88Ocnp1Z37rLi3NPbjoJKCJzOnb-OlKKPAa-tLZDP4Sy3xxsXzD6ENaRmFQSqtDw4dPIqouajTChREApsVCVEyz6aXNw4YryfScBGOmWSMpOiAZp7BAOOAPIDGBqSlvVJQ0pTkLOXKdXqlk14S1W9o2q5X8c7V425Em7nMH8ie3N0j_y0XfCpVSepKUVJBYofn2sY5BV/p.jpeg"
]
}
22 changes: 11 additions & 11 deletions src/config/app.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
import { loadEnv } from '../helpers/load-env.js';
import { validateEnv } from '../helpers/validate-env.js';
import { startBot } from './bot.js';
import { connectToDb } from './database.js';
import debugCreator from 'debug';
import { loadEnv } from "../helpers/load-env.js";
import { validateEnv } from "../helpers/validate-env.js";
import { startBot } from "./bot.js";
import { connectToDb } from "./database.js";
import debugCreator from "debug";

const debug = debugCreator('app:');
const debug = debugCreator("app:");

export async function startApp() {
debug('Starting app...');
debug("Starting app...");
try {
loadEnv();
validateEnv(['TELEGRAM_TOKEN', 'DB_CONNECTION_STRING']);
validateEnv(["TELEGRAM_TOKEN", "DB_CONNECTION_STRING"]);
} catch (error) {
console.error('Error occurred while loading environment:', error);
console.error("Error occurred while loading environment:", error);
process.exit(1);
}

let database;
try {
database = await connectToDb();
} catch (error) {
console.error('Error occurred while connecting to the database:', error);
console.error("Error occurred while connecting to the database:", error);
process.exit(2);
}

try {
await startBot(database);
} catch (error) {
console.error('Error occurred while starting the bot:', error);
console.error("Error occurred while starting the bot:", error);
process.exit(3);
}
}
34 changes: 19 additions & 15 deletions src/config/bot.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import type { I18n } from '@grammyjs/i18n/dist/source/i18n.js';
import { Bot as TelegramBot, session } from 'grammy';
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 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 { resolvePath } from "../helpers/resolve-path.js";
import { createReplyWithTextFunc } from "../services/context.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 { propertiesController } from "../controllers/properties.js";
import { fileIdController } from "../controllers/fileId.js";

function extendContext(bot: Bot, database: Database) {
bot.use(async (ctx, next) => {
Expand All @@ -22,15 +24,15 @@ function extendContext(bot: Bot, database: Database) {
ctx.db = database;

let chat: Chat | null = null;
if (ctx.chat.type !== 'private') {
if (ctx.chat.type !== "private") {
chat = await getOrCreateChat({
db: database,
chatId: ctx.chat.id,
title: ctx.chat.title
});
}

ctx.entities = {
ctx.config = {
user: await getOrCreatePlayer({
db: database,
userId: ctx.from.id,
Expand All @@ -52,10 +54,12 @@ function setupMiddlewares(bot: Bot, localeEngine: I18n) {
function setupControllers(bot: Bot) {
bot.use(startController);
bot.use(stopController);
bot.use(propertiesController);
bot.use(fileIdController);
}

export async function startBot(database: Database) {
const localesPath = resolvePath(import.meta.url, '../locales');
const localesPath = resolvePath(import.meta.url, "../locales");
const i18n = initLocaleEngine(localesPath);
const bot = new TelegramBot<CustomContext>(process.env.TELEGRAM_TOKEN);
extendContext(bot, database);
Expand Down
11 changes: 6 additions & 5 deletions src/config/database.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { MongoClient } from 'mongodb';
import type { Chat, Database, User } from '../types/database.js';
import { MongoClient } from "mongodb";
import type { Chat, Database, Property, User } from "../types/database.js";

export async function connectToDb() {
const client = new MongoClient(process.env.DB_CONNECTION_STRING);
await client.connect();
const mongoDb = client.db();
const user = mongoDb.collection<User>('user');
const chat = mongoDb.collection<Chat>('chat');
const database: Database = { user, chat };
const user = mongoDb.collection<User>("user");
const chat = mongoDb.collection<Chat>("chat");
const property = mongoDb.collection<Property>("properties");
const database: Database = { user, chat, property };
return database;
}
4 changes: 2 additions & 2 deletions src/config/locale-engine.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { I18n } from '@grammyjs/i18n';
import { I18n } from "@grammyjs/i18n";

export function initLocaleEngine(path: string, defaultLanguage = 'en') {
export function initLocaleEngine(path: string, defaultLanguage = "en") {
const i18n = new I18n({
directory: path,
defaultLanguage: defaultLanguage,
Expand Down
11 changes: 11 additions & 0 deletions src/controllers/fileId.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Composer } from "grammy";
import type { CustomContext } from "../types/context.js";

export const fileIdController = new Composer<CustomContext>();
fileIdController.on("message", async ctx => {
const fileId = ctx.update.message?.video?.file_id;
if (!fileId) {
return;
}
await ctx.reply(`File ID: ${fileId}`);
});
28 changes: 28 additions & 0 deletions src/controllers/properties.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Composer } from "grammy";
import type { CustomContext } from "../types/context.js";
import type { Property } from "../types/database.js";
import {
generatePropertyDescription,
generatePropertyPhotoAlbum
} from "../services/Property/property.service.js";

export const propertiesController = new Composer<CustomContext>();

propertiesController.command("properties", async ctx => {
const properties = (await ctx.db.property.find({}).toArray()) as Property[];
const currentPropertyIndex = 0;

const currentProperty = properties[currentPropertyIndex];
const totalProperties = properties.length;

const { videoFileId: videoUrl, albumUrls } = currentProperty;

const propertyDescription = generatePropertyDescription(currentProperty);
const propertyPhotoAlbum = generatePropertyPhotoAlbum(albumUrls);
await ctx.reply(`Property ${currentPropertyIndex + 1}/${totalProperties}`);
await ctx.reply(propertyDescription, {
parse_mode: "MarkdownV2"
});
await ctx.replyWithVideo(videoUrl);
await ctx.replyWithMediaGroup(propertyPhotoAlbum);
});
12 changes: 6 additions & 6 deletions src/controllers/start.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Composer } from 'grammy';
import type { CustomContext } from '../types/context.js';
import { Composer } from "grammy";
import type { CustomContext } from "../types/context.js";

export const startController = new Composer<CustomContext>();
startController.command('start', async ctx => {
await ctx.text('start', {
name: ctx.entities.user.name,
chatName: ctx.entities.chat?.title ?? 'PM'
startController.command("start", async ctx => {
await ctx.text("start", {
name: ctx.config.user.name,
chatName: ctx.config.chat?.title ?? "PM"
});
});
Loading

0 comments on commit 289e974

Please sign in to comment.