Browse Source

Merge pull request #10 from naresh97/feature/promiseMigration

Feature/promise migration
pull/9/head
Nareshkumar Rao 3 years ago
committed by GitHub
parent
commit
e20eb2b4e7
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 82
      src/db/models/User.helper.ts
  2. 60
      src/db/utils.ts
  3. 55
      src/routes/CodeRoute.ts
  4. 25
      src/routes/CovidRoute.ts
  5. 42
      src/routes/LoginRoute.ts
  6. 67
      src/routes/TelegramWebhookRoute.ts
  7. 28
      src/routes/VerifyRoute.ts
  8. 38
      src/telegram.ts

82
src/db/models/User.helper.ts

@ -1,80 +1,60 @@
import { TelegramID, UserRowID, VerificationString } from "../../types"; import { TelegramID, UserRowID, VerificationString } from "../../types";
import { User, UserInstance } from "./User"; import { User, UserInstance } from "./User";
export function getUserByTelegramID(
telegramID: TelegramID,
callback: (user?: UserInstance, message?: string) => void
): void {
User.findOne({
export async function getUserByTelegramID(
telegramID: TelegramID
): Promise<UserInstance | null> {
const user = await User.findOne({
where: { where: {
telegram: telegramID, telegram: telegramID,
}, },
})
.then((result) => {
callback(!!result ? result : undefined);
})
.catch(() => {
callback(undefined);
}); });
return user;
} }
export function getUserByRowID(
rowID: UserRowID,
callback: (user?: UserInstance, message?: string) => void
): void {
User.findOne({
export async function getUserByRowID(
rowID: UserRowID
): Promise<UserInstance | null> {
const user = await User.findOne({
where: { where: {
id: rowID, id: rowID,
}, },
})
.then((result) => {
callback(!!result ? result : undefined);
})
.catch(() => {
callback(undefined);
}); });
return user;
} }
export function getUserByVerification(
verification: VerificationString,
callback: (user?: UserInstance, message?: string) => void
): void {
User.findOne({
export async function getUserByVerification(
verification: VerificationString
): Promise<UserInstance | null> {
const user = await User.findOne({
where: { where: {
verification: verification, verification: verification,
}, },
})
.then((result) => {
callback(!!result ? result : undefined);
})
.catch(() => {
callback(undefined);
}); });
return user;
} }
export function getUserCovidPositivity(telegramID: TelegramID, callback: (isInfected?: boolean) => void): void {
getUserByTelegramID(telegramID, user => {
if (!!user) {
const infectionDuration = Date.now() - +user.infectionDate;
export async function getUserCovidPositivity(
telegramID: TelegramID
): Promise<boolean> {
const user = await getUserByTelegramID(telegramID);
if (!user) throw new Error("User not found");
const infectionDuration = new Date().getTime() - user.infectionDate.getTime();
if (infectionDuration > 60 * 60 * 24 * 14 * 1000) { if (infectionDuration > 60 * 60 * 24 * 14 * 1000) {
setUserCovidPositivity(telegramID, false, success => {
callback(success ? false : undefined);
});
await setUserCovidPositivity(telegramID, false);
return false;
} else { } else {
callback(user.isInfected);
return user.isInfected;
} }
} else {
callback();
}
});
} }
export function setUserCovidPositivity(telegramID: TelegramID, infectionState: boolean, callback: (success: boolean) => void): void {
getUserByTelegramID(telegramID, user => {
if (!!user) {
export async function setUserCovidPositivity(
telegramID: TelegramID,
infectionState: boolean
): Promise<void> {
const user = await getUserByTelegramID(telegramID);
if (!user) throw new Error("User not found");
user.isInfected = infectionState; user.isInfected = infectionState;
user.infectionDate = new Date(); user.infectionDate = new Date();
user.save().then(() => callback(true)).catch(() => callback(false));
} else { callback(false) }
});
if (!(await user.save())) throw new Error("Could not save user state");
} }

60
src/db/utils.ts

@ -1,56 +1,30 @@
import { strings_en } from "../strings"; import { strings_en } from "../strings";
import { sendTelegramMessage } from "../telegram"; import { sendTelegramMessage } from "../telegram";
import { TelegramID, UserRowID } from "../types";
import { TelegramID } from "../types";
import { Contact } from "./models/Contact"; import { Contact } from "./models/Contact";
import { User } from "./models/User";
import { getUserByRowID, getUserByTelegramID } from "./models/User.helper";
import { User, UserInstance } from "./models/User";
import { getUserByTelegramID } from "./models/User.helper";
export function addContact(
export async function addContact(
userATelegram: TelegramID, userATelegram: TelegramID,
userBTelegram: TelegramID,
callback: (success: boolean, message?: string) => void
): void {
getUserByTelegramID(userATelegram, (userA) => {
getUserByTelegramID(userBTelegram, (userB) => {
userBTelegram: TelegramID
): Promise<void> {
const userA = await getUserByTelegramID(userATelegram);
const userB = await getUserByTelegramID(userBTelegram);
if (!userA || !userB) { if (!userA || !userB) {
callback(false, "Could not find user.");
return;
throw new Error("Could not found users");
} }
Contact.create({ user: userA.id, with: userB.id })
.then(() => {
console.log(
`Registering contact between ${userA.id} and ${userB.id}`
);
sendTelegramMessage(userB.telegram, strings_en.telegram_qr_scanned);
callback(true, "Successfully added contact");
})
.catch((e) => {
callback(false, e);
});
});
});
await Contact.create({ user: userA.id, with: userB.id });
await sendTelegramMessage(userB.telegram, strings_en.telegram_qr_scanned);
} }
export function createUser(
telegram: TelegramID,
callback: (success: boolean, message: string) => void
): void {
User.create({
export async function createUser(
telegram: TelegramID
): Promise<UserInstance | null> {
const user = await User.create({
telegram: telegram, telegram: telegram,
})
.then((user) => {
if (!user) {
callback(false, "Could not create user");
} else {
callback(true, "Success");
}
})
.catch((reason) => {
if (reason.name == "SequelizeUniqueConstraintError") {
callback(false, "User already exists");
} else {
callback(false, "Unknown error");
}
}); });
return user;
} }

55
src/routes/CodeRoute.ts

@ -5,41 +5,37 @@ import { TelegramID, VerificationString } from "../types";
import { User, UserInstance } from "../db/models/User"; import { User, UserInstance } from "../db/models/User";
import { getUserByTelegramID } from "../db/models/User.helper"; import { getUserByTelegramID } from "../db/models/User.helper";
export function CodeRoute(req: Request, res: Response) {
export async function CodeRoute(req: Request, res: Response) {
if (!req.session.userTelegramID) { if (!req.session.userTelegramID) {
res.status(401).send("Not logged in"); res.status(401).send("Not logged in");
return; return;
} }
createQRCode(req.session.userTelegramID, (err, url) => {
res.status(url ? 200 : 401).send({ error: err, data: url });
});
try {
const url = await createQRCode(req.session.userTelegramID);
res.send({ data: url });
} catch (error) {
res
.status(500)
.send({ error: error instanceof Error ? error.message : "Error" });
} }
function createQRCode(
telegram: TelegramID,
callback: (errorMessage: string | Error, url?: string) => void
): void {
getUserByTelegramID(telegram, (user) => {
!!user &&
refreshVerification(user, (result) => {
const verifyURL = `${
process.env.WEBSITE_URL
}/#/verify/${encodeURIComponent(result.verification)}`;
QRCode.toDataURL(
verifyURL,
{ width: 300, height: 300 } as QRCodeToDataURLOptions,
(error, url) => {
callback(error, url);
} }
);
});
});
async function createQRCode(telegram: TelegramID): Promise<string> {
const user = await getUserByTelegramID(telegram);
if (!user) throw new Error("User not found");
const newVerification = await refreshVerification(user);
const verifyURL = `${process.env.WEBSITE_URL}/#/verify/${encodeURIComponent(
newVerification
)}`;
return await QRCode.toDataURL(verifyURL, {
width: 300,
height: 300,
} as QRCodeToDataURLOptions);
} }
function refreshVerification(
user: UserInstance,
callback: (success: UserInstance) => void
): void {
async function refreshVerification(
user: UserInstance
): Promise<VerificationString> {
let newVerification = bcrypt let newVerification = bcrypt
.hashSync(`${new Date().getTime()}-${user.telegram}`, 5) .hashSync(`${new Date().getTime()}-${user.telegram}`, 5)
.replace(/[^a-zA-Z0-9]+/g, "") as VerificationString; .replace(/[^a-zA-Z0-9]+/g, "") as VerificationString;
@ -48,7 +44,6 @@ function refreshVerification(
newVerification.length / 2 newVerification.length / 2
) as VerificationString; ) as VerificationString;
user.verification = newVerification; user.verification = newVerification;
user.save().then((result) => {
callback(result);
});
await user.save();
return newVerification;
} }

25
src/routes/CovidRoute.ts

@ -1,26 +1,33 @@
import { Request, Response } from "express"; import { Request, Response } from "express";
import { getUserCovidPositivity, setUserCovidPositivity } from "../db/models/User.helper";
import {
getUserCovidPositivity,
setUserCovidPositivity,
} from "../db/models/User.helper";
interface CovidRouteRequest extends Request { interface CovidRouteRequest extends Request {
body: { body: {
setPositive: boolean; setPositive: boolean;
}
};
} }
export function CovidRoute(req: CovidRouteRequest, res:Response){
export async function CovidRoute(req: CovidRouteRequest, res: Response) {
if (!req.session.userTelegramID) { if (!req.session.userTelegramID) {
res.status(401).send("Not logged in"); res.status(401).send("Not logged in");
return; return;
} }
try {
if (req.body.setPositive) { if (req.body.setPositive) {
setUserCovidPositivity(req.session.userTelegramID, true, success=>{
await setUserCovidPositivity(req.session.userTelegramID, true);
res.send({ covidPositive: true }); res.send({ covidPositive: true });
});
} else { } else {
getUserCovidPositivity(req.session.userTelegramID, isInfected=>{
const isInfected = await getUserCovidPositivity(
req.session.userTelegramID
);
res.send({ covidPositive: isInfected }); res.send({ covidPositive: isInfected });
});
}
} catch (error) {
res
.send(500)
.send({ error: error instanceof Error ? error.message : "Error" });
} }
} }

42
src/routes/LoginRoute.ts

@ -16,40 +16,44 @@ interface LoginRequest extends Request {
}; };
} }
export function LoginRoute(req: LoginRequest, res: Response) {
export async function LoginRoute(req: LoginRequest, res: Response) {
const telegramResponse = req.body.telegramResponse; const telegramResponse = req.body.telegramResponse;
authUser(telegramResponse, (authorized) => {
try {
const authorized = await authUser(telegramResponse);
if (authorized) { if (authorized) {
// User is already logged in // User is already logged in
if (req.session.userTelegramID == telegramResponse.id) { if (req.session.userTelegramID == telegramResponse.id) {
res.send({ authorized: authorized }); res.send({ authorized: authorized });
return; return;
} }
// User not logged in
const verified = req.session.isVerified; const verified = req.session.isVerified;
const verifiedBy = req.session.verifiedByTelegramID; const verifiedBy = req.session.verifiedByTelegramID;
req.session.regenerate(() => {
req.session.regenerate(async () => {
req.session.userTelegramID = telegramResponse.id; req.session.userTelegramID = telegramResponse.id;
if (verified) { if (verified) {
addContact(telegramResponse.id, verifiedBy, (success) => {
await addContact(telegramResponse.id, verifiedBy);
res.send({ res.send({
authorized: authorized,
contactSuccess: success,
});
authorized: true,
contactSuccess: true,
}); });
} else { } else {
res.send({ authorized: authorized }); res.send({ authorized: authorized });
} }
}); });
} else { } else {
res.status(401).send(authorized);
res.status(401).send({ error: "Unauthorized" });
}
} catch (error) {
res
.status(500)
.send({ error: error instanceof Error ? error.message : "Error" });
} }
});
} }
function authUser(
telegramResponse: TelegramLoginResponse,
callback: (authorized: boolean, message?: string) => void
): void {
async function authUser(
telegramResponse: TelegramLoginResponse
): Promise<boolean> {
let dataCheckArray = []; let dataCheckArray = [];
for (const [key, value] of Object.entries(telegramResponse)) { for (const [key, value] of Object.entries(telegramResponse)) {
@ -71,17 +75,13 @@ function authUser(
const authorized = confirmationHash == telegramResponse.hash; const authorized = confirmationHash == telegramResponse.hash;
if (!authorized) { if (!authorized) {
callback(false);
return;
return false;
} }
getUserByTelegramID(telegramResponse.id, (user) => {
const user = await getUserByTelegramID(telegramResponse.id);
if (!!user) { if (!!user) {
callback(true);
return true;
} else { } else {
createUser(telegramResponse.id, (success, message) => {
callback(success, message);
});
return !!(await createUser(telegramResponse.id));
} }
});
} }

67
src/routes/TelegramWebhookRoute.ts

@ -19,13 +19,13 @@ interface TelegramWebhookRequest extends Request {
}; };
} }
export function TelegramWebhookRoute(
export async function TelegramWebhookRoute(
req: TelegramWebhookRequest, req: TelegramWebhookRequest,
res: Response res: Response
) { ) {
try { try {
if (req.body.message.connected_website) { if (req.body.message.connected_website) {
sendTelegramMessage(
await sendTelegramMessage(
req.body.message.from.id, req.body.message.from.id,
"Thanks for using OurSejahtera! Let's stay safer together <3" "Thanks for using OurSejahtera! Let's stay safer together <3"
); );
@ -33,67 +33,46 @@ export function TelegramWebhookRoute(
const messageText = req.body.message.text; const messageText = req.body.message.text;
const telegramID = req.body.message.from.id; const telegramID = req.body.message.from.id;
if (messageText.toLowerCase() == "/covidpositive") { if (messageText.toLowerCase() == "/covidpositive") {
userInfected(telegramID, (success) => {
if (success) {
sendTelegramMessage(
await userInfected(telegramID);
await sendTelegramMessage(
telegramID, telegramID,
strings_en.telegram_inform_positive strings_en.telegram_inform_positive
); );
informContacts(telegramID);
} else {
sendTelegramMessage(telegramID, "Sorry, something went wrong.");
}
});
await informContacts(telegramID);
} }
} }
} catch (e) { } catch (e) {
console.log("Could not get Telegram Message");
console.log(
e instanceof Error ? e.message : "Could not get Telegram Message"
);
} }
res.send(); res.send();
} }
function informContacts(telegramID: TelegramID) {
getUserByTelegramID(telegramID, (user) => {
if (user) {
Contact.findAll({
async function informContacts(telegramID: TelegramID): Promise<void> {
const user = await getUserByTelegramID(telegramID);
if (!user) throw new Error("User not found");
const contacts = await Contact.findAll({
where: { where: {
[Op.or]: [{ user: user.id }, { with: user.id }], [Op.or]: [{ user: user.id }, { with: user.id }],
}, },
}).then((result) => {
result.forEach((contact) => {
const otherPersonID =
contact.user == user.id ? contact.with : contact.user;
getUserByRowID(otherPersonID, (otherUser) => {
otherUser &&
sendTelegramMessage(
});
contacts.forEach(async (contact) => {
const otherPersonID = contact.user == user.id ? contact.with : contact.user;
const otherUser = await getUserByRowID(otherPersonID);
if (!otherUser) throw new Error("Other user does not exist");
await sendTelegramMessage(
otherUser.telegram, otherUser.telegram,
strings_en.telegram_inform_infect strings_en.telegram_inform_infect
); );
}); });
});
});
}
});
} }
function userInfected(
telegramID: TelegramID,
callback: (success: boolean) => void
): void {
getUserByTelegramID(telegramID, (user) => {
if (!!user) {
async function userInfected(telegramID: TelegramID): Promise<void> {
const user = await getUserByTelegramID(telegramID);
if (!user) throw new Error("User not found");
user.isInfected = true; user.isInfected = true;
user
.save()
.then((result) => {
callback(!!result);
})
.catch(() => {
callback(false);
});
} else {
callback(false);
}
});
await user.save();
} }

28
src/routes/VerifyRoute.ts

@ -10,35 +10,29 @@ interface VerifyRequest extends Request {
}; };
} }
export function VerifyRoute(req: VerifyRequest, res: Response) {
getUserByVerification(
decodeURIComponent(req.body.id) as VerificationString,
(verifiedByUser, message) => {
export async function VerifyRoute(req: VerifyRequest, res: Response) {
const verifiedByUser = await getUserByVerification(
decodeURIComponent(req.body.id) as VerificationString
);
try{
if (!!verifiedByUser) { if (!!verifiedByUser) {
req.session.isVerified = !!verifiedByUser; req.session.isVerified = !!verifiedByUser;
req.session.verifiedByTelegramID = verifiedByUser.telegram; req.session.verifiedByTelegramID = verifiedByUser.telegram;
if (req.session.userTelegramID) { if (req.session.userTelegramID) {
// If Logged In // If Logged In
addContact(
req.session.userTelegramID,
verifiedByUser.telegram,
(success, message) => {
res
.status(success ? 200 : 400)
.send({ success: success, message: message, loggedIn: true });
}
);
await addContact(req.session.userTelegramID, verifiedByUser.telegram);
res.send({ success: true, loggedIn: true });
} else { } else {
// If Not Logged In // If Not Logged In
res.send({ res.send({
success: !!verifiedByUser,
message: message,
success: false,
loggedIn: false, loggedIn: false,
}); });
} }
} else { } else {
res.status(400).send({ success: !!verifiedByUser, message: message });
res.status(400).send({ success: false });
} }
}catch(e){
res.status(500).send({error: e instanceof Error ? e.message : "Error"});
} }
);
} }

38
src/telegram.ts

@ -1,42 +1,30 @@
import axios from "axios"; import axios from "axios";
import { TelegramID } from "./types"; import { TelegramID } from "./types";
export function setTelegramWebHook(
callback: (success: boolean) => void = () => {}
): void {
export async function setTelegramWebHook(): Promise<void> {
const url = `https://api.telegram.org/bot${process.env.TELEGRAM_TOKEN}/setWebhook`; const url = `https://api.telegram.org/bot${process.env.TELEGRAM_TOKEN}/setWebhook`;
axios
.post(url, {
await axios.post(url, {
url: `${process.env.SERVER_API_URL}/${process.env.TELEGRAM_SECRET}`, url: `${process.env.SERVER_API_URL}/${process.env.TELEGRAM_SECRET}`,
allowed_updates: [], allowed_updates: [],
drop_pending_updates: true, drop_pending_updates: true,
})
.then((res) => {
callback(!!res);
})
.catch((err) => {
callback(!!err);
}); });
} }
export function sendTelegramMessage(
export async function sendTelegramMessage(
telegramID: TelegramID, telegramID: TelegramID,
message: string,
callback: (success: boolean) => void = () => {}
): void {
message: string
): Promise<void> {
const url = `https://api.telegram.org/bot${process.env.TELEGRAM_TOKEN}/sendMessage`; const url = `https://api.telegram.org/bot${process.env.TELEGRAM_TOKEN}/sendMessage`;
axios
.post(url, {
const response = await axios.post(url, {
chat_id: telegramID, chat_id: telegramID,
text: message, text: message,
})
.then((res) => {
callback(!!res);
})
.catch((err) => {
console.error("Problem sending Telegram message.");
callback(!!err);
}); });
} }
setTelegramWebHook();
setTelegramWebHook()
.catch(error=>{
console.error("Error setting Telegram Webhook");
error instanceof Error && console.error(error.message);
});

Loading…
Cancel
Save