mirror of
https://codeberg.org/keyoxide/doipjs.git
synced 2024-12-22 22:49:28 -07:00
Implement Telegram support
This commit is contained in:
parent
2958ba7d2d
commit
8466ef934e
6 changed files with 220 additions and 0 deletions
|
@ -18,6 +18,7 @@ const list = [
|
||||||
'irc',
|
'irc',
|
||||||
'xmpp',
|
'xmpp',
|
||||||
'matrix',
|
'matrix',
|
||||||
|
'telegram',
|
||||||
'twitter',
|
'twitter',
|
||||||
'reddit',
|
'reddit',
|
||||||
'liberapay',
|
'liberapay',
|
||||||
|
@ -39,6 +40,7 @@ const data = {
|
||||||
irc: require('./irc'),
|
irc: require('./irc'),
|
||||||
xmpp: require('./xmpp'),
|
xmpp: require('./xmpp'),
|
||||||
matrix: require('./matrix'),
|
matrix: require('./matrix'),
|
||||||
|
telegram: require('./telegram'),
|
||||||
twitter: require('./twitter'),
|
twitter: require('./twitter'),
|
||||||
reddit: require('./reddit'),
|
reddit: require('./reddit'),
|
||||||
liberapay: require('./liberapay'),
|
liberapay: require('./liberapay'),
|
||||||
|
|
78
src/claimDefinitions/telegram.js
Normal file
78
src/claimDefinitions/telegram.js
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 Yarmo Mackenbach
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
const E = require('../enums')
|
||||||
|
|
||||||
|
const reURI = /^tg:user=([a-zA-Z0-9_]{5,32})&chat=([a-zA-Z0-9_]{5,32})/
|
||||||
|
|
||||||
|
const processURI = (uri) => {
|
||||||
|
const match = uri.match(reURI)
|
||||||
|
|
||||||
|
return {
|
||||||
|
serviceprovider: {
|
||||||
|
type: 'communication',
|
||||||
|
name: 'telegram'
|
||||||
|
},
|
||||||
|
match: {
|
||||||
|
regularExpression: reURI,
|
||||||
|
isAmbiguous: false
|
||||||
|
},
|
||||||
|
profile: {
|
||||||
|
display: `@${match[1]}`,
|
||||||
|
uri: `https://t.me/${match[1]}`,
|
||||||
|
qr: null
|
||||||
|
},
|
||||||
|
proof: {
|
||||||
|
uri: null,
|
||||||
|
request: {
|
||||||
|
fetcher: E.Fetcher.TELEGRAM,
|
||||||
|
access: E.ProofAccess.GRANTED,
|
||||||
|
format: E.ProofFormat.JSON,
|
||||||
|
data: {
|
||||||
|
user: match[1],
|
||||||
|
chat: match[2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
claim: {
|
||||||
|
format: E.ClaimFormat.FINGERPRINT,
|
||||||
|
relation: E.ClaimRelation.EQUALS,
|
||||||
|
path: ['text']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const tests = [
|
||||||
|
{
|
||||||
|
uri: 'tg:user=alice&chat=foobar',
|
||||||
|
shouldMatch: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uri: 'tg:user=complex_user_1234&chat=complex_chat_1234',
|
||||||
|
shouldMatch: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uri: 'tg:user=&chat=foobar',
|
||||||
|
shouldMatch: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uri: 'tg:user=foobar&chat=',
|
||||||
|
shouldMatch: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
exports.reURI = reURI
|
||||||
|
exports.processURI = processURI
|
||||||
|
exports.tests = tests
|
|
@ -49,6 +49,8 @@ const Fetcher = {
|
||||||
XMPP: 'xmpp',
|
XMPP: 'xmpp',
|
||||||
/** HTTP request to Matrix API */
|
/** HTTP request to Matrix API */
|
||||||
MATRIX: 'matrix',
|
MATRIX: 'matrix',
|
||||||
|
/** HTTP request to Telegram API */
|
||||||
|
TELEGRAM: 'telegram',
|
||||||
/** HTTP request to Twitter API */
|
/** HTTP request to Twitter API */
|
||||||
TWITTER: 'twitter'
|
TWITTER: 'twitter'
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,5 +18,6 @@ exports.dns = require('./dns')
|
||||||
exports.http = require('./http')
|
exports.http = require('./http')
|
||||||
exports.irc = require('./irc')
|
exports.irc = require('./irc')
|
||||||
exports.matrix = require('./matrix')
|
exports.matrix = require('./matrix')
|
||||||
|
exports.telegram = require('./telegram')
|
||||||
exports.twitter = require('./twitter')
|
exports.twitter = require('./twitter')
|
||||||
exports.xmpp = require('./xmpp')
|
exports.xmpp = require('./xmpp')
|
||||||
|
|
110
src/fetcher/telegram.js
Normal file
110
src/fetcher/telegram.js
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 Yarmo Mackenbach
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
const axios = require('axios')
|
||||||
|
const validator = require('validator')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @module fetcher/telegram
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The single request's timeout value in milliseconds
|
||||||
|
* This fetcher makes two requests in total
|
||||||
|
* @constant {number} timeout
|
||||||
|
*/
|
||||||
|
module.exports.timeout = 5000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a fetch request
|
||||||
|
* @function
|
||||||
|
* @async
|
||||||
|
* @param {object} data - Data used in the request
|
||||||
|
* @param {string} data.chat - Telegram public chat username
|
||||||
|
* @param {string} data.user - Telegram user username
|
||||||
|
* @param {object} opts - Options used to enable the request
|
||||||
|
* @param {string} opts.claims.telegram.token - The Telegram Bot API token
|
||||||
|
* @returns {object|string}
|
||||||
|
*/
|
||||||
|
module.exports.fn = async (data, opts) => {
|
||||||
|
let timeoutHandle
|
||||||
|
const timeoutPromise = new Promise((resolve, reject) => {
|
||||||
|
timeoutHandle = setTimeout(
|
||||||
|
() => reject(new Error('Request was timed out')),
|
||||||
|
data.fetcherTimeout ? data.fetcherTimeout : module.exports.timeout
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const apiPromise = (method) => new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
validator.isAscii(opts.claims.telegram.token)
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(`Telegram fetcher was not set up properly (${err.message})`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data.chat || !data.user) {
|
||||||
|
reject(new Error('Both chat name and user name must be provided'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = `https://api.telegram.org/bot${opts.claims.telegram.token}/${method}?chat_id=@${data.chat}`
|
||||||
|
axios.get(url, {
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json',
|
||||||
|
'User-Agent': `doipjs/${require('../../package.json').version}`
|
||||||
|
},
|
||||||
|
validateStatus: (status) => status === 200
|
||||||
|
})
|
||||||
|
.then(res => resolve(res.data))
|
||||||
|
.catch(e => reject(e))
|
||||||
|
})
|
||||||
|
|
||||||
|
const fetchPromise = apiPromise('getChatAdministrators').then(admins => {
|
||||||
|
if (!admins.ok) {
|
||||||
|
throw new Error('Request to get chat administrators failed')
|
||||||
|
}
|
||||||
|
|
||||||
|
return apiPromise('getChat').then(chat => {
|
||||||
|
if (!chat.ok) {
|
||||||
|
throw new Error('Request to get chat info failed')
|
||||||
|
}
|
||||||
|
|
||||||
|
let creator
|
||||||
|
for (const admin of admins.result) {
|
||||||
|
if (admin.status === 'creator') {
|
||||||
|
creator = admin.user.username
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!chat.result.description) {
|
||||||
|
throw new Error('There is no chat description')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (creator !== data.user) {
|
||||||
|
throw new Error('User doesn\'t match')
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
user: creator,
|
||||||
|
text: chat.result.description
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return Promise.race([fetchPromise, timeoutPromise]).then((result) => {
|
||||||
|
clearTimeout(timeoutHandle)
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
}
|
|
@ -28,6 +28,9 @@ const opts = {
|
||||||
instance: process.env.MATRIX_INSTANCE || null,
|
instance: process.env.MATRIX_INSTANCE || null,
|
||||||
accessToken: process.env.MATRIX_ACCESS_TOKEN || null
|
accessToken: process.env.MATRIX_ACCESS_TOKEN || null
|
||||||
},
|
},
|
||||||
|
telegram: {
|
||||||
|
token: process.env.TELEGRAM_TOKEN || null
|
||||||
|
},
|
||||||
xmpp: {
|
xmpp: {
|
||||||
service: process.env.XMPP_SERVICE || null,
|
service: process.env.XMPP_SERVICE || null,
|
||||||
username: process.env.XMPP_USERNAME || null,
|
username: process.env.XMPP_USERNAME || null,
|
||||||
|
@ -172,6 +175,30 @@ router.get(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Telegram route
|
||||||
|
router.get(
|
||||||
|
'/get/telegram', query('chat').isString(),
|
||||||
|
async (req, res) => {
|
||||||
|
if (!opts.claims.telegram.token) {
|
||||||
|
return res.status(501).json({ errors: 'Telegram not enabled on server' })
|
||||||
|
}
|
||||||
|
|
||||||
|
const errors = validationResult(req)
|
||||||
|
if (!errors.isEmpty()) {
|
||||||
|
return res.status(400).json({ errors: errors.array() })
|
||||||
|
}
|
||||||
|
|
||||||
|
fetcher.telegram
|
||||||
|
.fn(req.query, opts)
|
||||||
|
.then((data) => {
|
||||||
|
return res.status(200).send(data)
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
return res.status(400).json({ errors: err.message ? err.message : err })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// IRC route
|
// IRC route
|
||||||
router.get('/get/irc', query('nick').isString(), async (req, res) => {
|
router.get('/get/irc', query('nick').isString(), async (req, res) => {
|
||||||
if (!opts.claims.irc.nick) {
|
if (!opts.claims.irc.nick) {
|
||||||
|
|
Loading…
Reference in a new issue