import { createHash, createHmac } from 'crypto';
import {
Context, ForbiddenError, Handler, Schema, Service,
} from 'hydrooj';
// from https://www.svgrepo.com/svg/333610/telegram
// eslint-disable-next-line max-len
const icon = '';
export default class TelegramService extends Service {
static inject = ['oauth'];
static Config = Schema.object({
token: Schema.string().role('secret').required(),
botLogin: Schema.string().required(),
endpoint: Schema.string().default('https://api.telegram.org/bot'),
canRegister: Schema.boolean().default(false),
});
constructor(ctx: Context, config: ReturnType) {
super(ctx, 'oauth.telegram');
ctx.oauth.provide('telegram', {
text: 'Login with Telegram',
name: 'Telegram',
icon,
canRegister: config.canRegister,
callback: async function callback({ payload }) {
let parsed;
try {
parsed = JSON.parse(payload);
} catch (e) {
throw new ForbiddenError('Invalid payload');
}
const hash = parsed.hash;
delete parsed.hash;
const dataCheckString = Object.keys(parsed).sort().map((key) => (`${key}=${parsed[key]}`)).join('\n');
const secretKey = createHash('sha256').update(config.token).digest();
const dataCheckSum = createHmac('sha256', secretKey).update(dataCheckString).digest('hex');
if (hash !== dataCheckSum) throw new ForbiddenError('Invalid hash');
const {
id, first_name, last_name, username, photo_url,
} = parsed;
const ret = {
_id: id.toString(),
email: `${id}@telegram.local`,
bio: '',
uname: [`${first_name} ${last_name}`, username, `telegram${id.toString()}`].filter((i) => i),
avatar: `url:${photo_url}`,
};
if (!ret.email) throw new ForbiddenError("You don't have a verified email.");
return ret;
},
async get(this: Handler) {
this.response.body = { botLogin: config.botLogin };
this.response.template = 'telegram_login.html';
},
});
ctx.i18n.load('zh', {
'Login With Telegram': '使用 Telegram 登录',
});
}
}