自建CloudFlare Serverless Worker反代Telegram通知+支持Post

之前写过如何开启Telegram的通知(本馆档案),但默认的API只支持GET(update2021_02_14: 其实支持post的)。同时,因为telegram在国内被封锁,所以如果通过cloudflare进行无国界的反代就成了一个有意思的话题。

之前的本馆档案

Worker JS 代码 – 主要都花在处理post数据上了

版本1 – 必须要把所有的参数(botid+chat_id)都带上; 纯粹的反代

const whitelist = ["/bot888518123:"];
const tg_host = "api.telegram.org";

addEventListener('fetch', event => {
    event.respondWith(handleRequest(event.request))
})

function validate(path) {
    for (var i = 0; i < whitelist.length; i++) {
        if (path.startsWith(whitelist[i]))
            return true;
    }
    return false;
}

async function handleRequest(request) {
    var u = new URL(request.url);
    u.host = tg_host;
    if (!validate(u.pathname))
        return new Response('Unauthorized', {
            status: 403
        });
    var req = new Request(u, {
        method: request.method,
        headers: request.headers,
        body: request.body
    });
    const result = await fetch(req);
    return result;
}

版本2 – 支持各种post格式;还可以写死botid和chatid


const OPT = {
  botid : 'bot1577XXXXX:YYYYYYYYtWBcXa0Fj7qHzLY8hTbqfzo',//bot id
  chatid:'-1001XXXXXX',//chatid
}

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

/**
* Respond to the request
* @param {Request} request
*/
async function handleRequest(request) {
  // msg text
  let text = "empty_text";

  if (request.method === "POST") {
    const ret = await readRequestBody(request);
    text = ret || text;
    // const requestString = JSON.stringify(requestObject);
    //console.log(params)
  } else if (request.method === "GET") {
    let url = new URL(request.url);
    text = url.searchParams.get('text') || text;
  }

  console.log(text)
  // https://api.telegram.org/botXXXXXX/sendMessage?chat_id=YYYYYY&text=#NEZHA#
  //发送消息
  return fetch("https://api.telegram.org/"+OPT.botid+"/sendMessage?chat_id="+OPT.chatid+"&text="+text,{
    method:'get'
  });
}


/**
 * readRequestBody reads in the incoming request body
 * Use await readRequestBody(..) in an async function to get the string
 * @param {Request} request the incoming request to read from
 */
async function readRequestBody(request) {
  const { headers } = request;
  const contentType = headers.get("content-type") || ""
  console.log(contentType);

  if (contentType.includes("application/json")) {
    console.log(1);
    let params = await request.json();
    console.log(params);
    return params['text'];
    //return JSON.stringify(await request.json())
  }
  else if (contentType.includes("application/text") || contentType.includes("text/html")|| contentType.includes("application/x-www-form-urlencoded")) {
    console.log(2);
    //console.log(typeof(await request.text()));
    let params = new URLSearchParams(await request.text());
    return params.get('text');
    //return await request.text()
  }
  else if (contentType.includes("form")) {
    console.log(4);
    const formData = await request.formData()
    const params = {}
    for (const entry of formData.entries()) {
      params[entry[0]] = entry[1]
    }
    return params.get('text');
    //return JSON.stringify(body)
  } else return "";
}

新域名 + Worker + 新路由

Leave a Reply