mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-07-06 14:52:09 +08:00
feat: telegram bot unbind && delete address (#254)
This commit is contained in:
159
worker/src/common.ts
Normal file
159
worker/src/common.ts
Normal file
@@ -0,0 +1,159 @@
|
||||
import { Context } from 'hono';
|
||||
import { Jwt } from 'hono/utils/jwt'
|
||||
|
||||
import { getDomains, getStringValue } from './utils';
|
||||
import { HonoCustomType } from './types';
|
||||
import { CONSTANTS } from './constants';
|
||||
import { unbindTelegramByAddress } from './telegram_api/common';
|
||||
|
||||
export const newAddress = async (
|
||||
c: Context<HonoCustomType>,
|
||||
name: string, domain: string | undefined | null,
|
||||
enablePrefix: boolean
|
||||
): Promise<{ address: string, jwt: string }> => {
|
||||
// remove special characters
|
||||
name = name.replace(/[^a-zA-Z0-9.]/g, '')
|
||||
// check name length
|
||||
if (name.length < 0) {
|
||||
throw new Error("Name too short")
|
||||
}
|
||||
// create address
|
||||
if (enablePrefix) {
|
||||
name = getStringValue(c.env.PREFIX) + name;
|
||||
}
|
||||
if (name.length >= 30) {
|
||||
throw new Error("Name too long (max 30)")
|
||||
}
|
||||
// check domain, generate random domain
|
||||
const domains = getDomains(c);
|
||||
if (!domain || !domains.includes(domain)) {
|
||||
domain = domains[Math.floor(Math.random() * domains.length)];
|
||||
}
|
||||
// create address
|
||||
name = name + "@" + domain;
|
||||
try {
|
||||
const { success } = await c.env.DB.prepare(
|
||||
`INSERT INTO address(name) VALUES(?)`
|
||||
).bind(name).run();
|
||||
if (!success) {
|
||||
throw new Error("Failed to create address")
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.message && e.message.includes("UNIQUE")) {
|
||||
throw new Error("Address already exists")
|
||||
}
|
||||
throw new Error("Failed to create address")
|
||||
}
|
||||
const address_id = await c.env.DB.prepare(
|
||||
`SELECT id FROM address where name = ?`
|
||||
).bind(name).first<number>("id");
|
||||
// create jwt
|
||||
const jwt = await Jwt.sign({
|
||||
address: name,
|
||||
address_id: address_id
|
||||
}, c.env.JWT_SECRET, "HS256")
|
||||
return {
|
||||
jwt: jwt,
|
||||
address: name,
|
||||
}
|
||||
}
|
||||
|
||||
export const cleanup = async (
|
||||
c: Context<HonoCustomType>,
|
||||
cleanType: string | undefined | null,
|
||||
cleanDays: number | undefined | null
|
||||
): Promise<boolean> => {
|
||||
if (!cleanType || !cleanDays || cleanDays < 0 || cleanDays > 30) {
|
||||
throw new Error("Invalid cleanType or cleanDays")
|
||||
}
|
||||
console.log(`Cleanup ${cleanType} before ${cleanDays} days`);
|
||||
switch (cleanType) {
|
||||
case "mails":
|
||||
await c.env.DB.prepare(`
|
||||
DELETE FROM raw_mails WHERE created_at < datetime('now', '-${cleanDays} day')`
|
||||
).run();
|
||||
break;
|
||||
case "mails_unknow":
|
||||
await c.env.DB.prepare(`
|
||||
DELETE FROM raw_mails WHERE address NOT IN
|
||||
(select name from address) AND created_at < datetime('now', '-${cleanDays} day')`
|
||||
).run();
|
||||
break;
|
||||
case "sendbox":
|
||||
await c.env.DB.prepare(`
|
||||
DELETE FROM sendbox WHERE created_at < datetime('now', '-${cleanDays} day')`
|
||||
).run();
|
||||
break;
|
||||
default:
|
||||
throw new Error("Invalid cleanType")
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: need senbox delete?
|
||||
*/
|
||||
export const deleteAddressWithData = async (
|
||||
c: Context<HonoCustomType>,
|
||||
address: string | undefined | null,
|
||||
address_id: number | undefined | null
|
||||
): Promise<boolean> => {
|
||||
if (!address && !address_id) {
|
||||
throw new Error("Address or address_id required")
|
||||
}
|
||||
// get address_id or address
|
||||
if (!address_id) {
|
||||
address_id = await c.env.DB.prepare(
|
||||
`SELECT id FROM address where name = ?`
|
||||
).bind(address).first<number>("id");
|
||||
} else if (!address) {
|
||||
address = await c.env.DB.prepare(
|
||||
`SELECT name FROM address where id = ?`
|
||||
).bind(address_id).first<string>("name");
|
||||
}
|
||||
// check address again
|
||||
if (!address || !address_id) {
|
||||
throw new Error("Can't find address");
|
||||
}
|
||||
// unbind telegram
|
||||
await unbindTelegramByAddress(c, address);
|
||||
// delete address and related data
|
||||
const { success: mailSuccess } = await c.env.DB.prepare(
|
||||
`DELETE FROM raw_mails WHERE address = ? `
|
||||
).bind(address).run();
|
||||
const { success: sendAccess } = await c.env.DB.prepare(
|
||||
`DELETE FROM address_sender WHERE address = ? `
|
||||
).bind(address).run();
|
||||
const { success: addressSuccess } = await c.env.DB.prepare(
|
||||
`DELETE FROM users_address WHERE address_id = ? `
|
||||
).bind(address_id).run();
|
||||
const { success } = await c.env.DB.prepare(
|
||||
`DELETE FROM address WHERE name = ? `
|
||||
).bind(address).run();
|
||||
if (!success || !mailSuccess || !addressSuccess || !sendAccess) {
|
||||
throw new Error("Failed to delete address")
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export const handleListQuery = async (
|
||||
c: Context<HonoCustomType>,
|
||||
query: string, countQuery: string, params: string[],
|
||||
limit: number | undefined | null,
|
||||
offset: number | undefined | null
|
||||
): Promise<Response> => {
|
||||
if (!limit || limit < 0 || limit > 100) {
|
||||
return c.text("Invalid limit", 400)
|
||||
}
|
||||
if (!offset || offset < 0) {
|
||||
return c.text("Invalid offset", 400)
|
||||
}
|
||||
const resultsQuery = `${query} order by id desc limit ? offset ?`;
|
||||
const { results } = await c.env.DB.prepare(resultsQuery).bind(
|
||||
...params, limit, offset
|
||||
).all();
|
||||
const count = offset == 0 ? await c.env.DB.prepare(
|
||||
countQuery
|
||||
).bind(...params).first("count") : 0;
|
||||
return c.json({ results, count });
|
||||
}
|
||||
Reference in New Issue
Block a user