This commit is contained in:
2026-07-15 19:33:49 +02:00
parent 2338858254
commit bdb6be1702
4 changed files with 95 additions and 6 deletions

View File

@@ -187,9 +187,10 @@ export default async bot => {
// --- LINKED ACCOUNT CHECK ---
let websiteUser = null;
if (e.type === 'matrix' || e.type === 'discord') {
// Identify lookup key
if (e.type === 'matrix' || e.type === 'discord' || e.type === 'tg') {
// Identify lookup key and type
// Matrix: Use unique ID (MXID)
// Telegram: Use numeric user ID (most stable, never changes)
// Discord: Use Nick or Username (Legacy) - TODO: Migration to ID recommended later
let lookupAlias = e.user.nick || e.user.username;
let lookupType = 'discord'; // default check
@@ -197,6 +198,9 @@ export default async bot => {
if (e.type === 'matrix') {
lookupAlias = e.user.account; // MXID
lookupType = 'matrix';
} else if (e.type === 'tg') {
lookupAlias = e.user.account; // numeric Telegram user ID as string
lookupType = 'telegram';
}
// Check DB
@@ -220,7 +224,8 @@ export default async bot => {
// Enforce Link for !w command
if (isWCommand && !websiteUser) {
await e.reply(`You must link your account to use this command. Go to ${cfg.main.url.full}/settings to link your ${e.type} account.`);
const linkType = e.type === 'tg' ? 'Telegram' : e.type;
await e.reply(`You must link your account to use this command. Go to ${cfg.main.url.full}/settings to link your ${linkType} account. Then send !link <TOKEN> to this bot.`);
return false;
}
}

View File

@@ -0,0 +1,78 @@
import db from "../sql.mjs";
import cfg from "../config.mjs";
export default async self => {
return [{
name: "telegram_link",
call: /^!link(?:\s+(.+))?$/i,
active: true,
clients: ["tg"],
f: async e => {
// Only for Telegram
if (e.type !== 'tg') return false;
let token = (e.args[0] || '').trim().toUpperCase();
// Scenario 1: User typed "!link" only (no token)
if (!token) {
await e.reply(`Please generate a link token on the website at ${cfg.main.url.full}/settings and then send: !link <TOKEN>`);
return true;
}
// Scenario 2: Processing a token
try {
// Find token in DB
const linkData = (await db`
SELECT user_id FROM link_token WHERE token = ${token}
`)[0];
if (!linkData) {
return await e.reply("Invalid or expired token. Please generate a new one at the website settings page.");
}
// Use the Telegram numeric user ID as the alias (most stable identifier)
const alias = e.user.account; // e.g. "123456789"
// Check if already linked to THIS user
const existing = await db`
SELECT 1 FROM user_alias
WHERE userid = ${linkData.user_id}
AND alias = ${alias}
AND type = 'telegram'
`;
if (existing.length > 0) {
return await e.reply("This Telegram account is already linked to your website profile.");
}
// Check if this Telegram account is linked to ANOTHER user (prevent hijacking)
const taken = await db`
SELECT 1 FROM user_alias
WHERE alias = ${alias}
AND type = 'telegram'
`;
if (taken.length > 0) {
return await e.reply("This Telegram account is already linked to a different website profile.");
}
// Perform Link
await db`
INSERT INTO user_alias (userid, alias, type)
VALUES (${linkData.user_id}, ${alias}, 'telegram')
ON CONFLICT DO NOTHING
`;
// Delete used token
await db`DELETE FROM link_token WHERE token = ${token}`;
const tgUsername = e.user.username ? `@${e.user.username}` : e.user.nick;
return await e.reply(`Successfully linked Telegram account ${tgUsername} (ID: ${alias}) to your website profile!`);
} catch (err) {
console.error("[Telegram Link] Error:", err);
return await e.reply("An internal error occurred while linking your account.");
}
}
}];
};

View File

@@ -1227,6 +1227,7 @@ process.on('uncaughtException', err => {
get cleanup_start_date() { return getCleanupStartDate(); },
get cleanup_end_date() { return getCleanupEndDate(); },
matrix_enabled: cfg.clients.find(c => c.type === 'matrix')?.enabled || false,
telegram_enabled: cfg.clients.find(c => c.type === 'tg')?.enabled || false,
ts: Date.now(),
get default_layout() { return getDefaultLayout(); },
show_koepfe: !!cfg.websrv.show_koepfe,