【发布时间】:2021-07-19 19:36:58
【问题描述】:
感谢这个社区的帮助,我已经完成了我的 Python Bot for telegram 以通过聊天发送 HTML5 游戏! 不幸的是,为了让机器人获取分数,我需要在机器人中实际设置一个 HTTP 服务器来执行此操作。通过我的研究,我似乎无法弄清楚如何在没有自签名的情况下使用 ssl 在 python 中创建服务器(因为当用户点击玩游戏时它会给出一个空白页面)。
我购买了一个域,它已经设置了我的 VPS IP 地址,尽管我有 Apache 的 ssl 证书...
有人可以帮我设置一下吗?由于发送和不安全的 HTTP 连接或自签名连接将导致应用程序内出现空白页面...
非常感谢!
Edit1:机器人代码:
import configparser, threading, requests, json, re, time, sys
from uuid import uuid4
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from telegram import InlineQueryResultGame, ParseMode, InputTextMessageContent
from telegram.ext import Updater, CommandHandler, CallbackQueryHandler, InlineQueryHandler, CommandHandler, CallbackContext
from http.server import HTTPServer, BaseHTTPRequestHandler
def error_callback(update, context):
logger.warning('Update "%s" caused error "%s"', update, context.error)
class Global:
def __init__(self):
return
class GameHTTPRequestHandler(BaseHTTPRequestHandler):
def __init__(self, *args):
BaseHTTPRequestHandler.__init__(self, *args)
def do_GET(self):
if "#" in self.path:
self.path = self.path.split("#")[0]
if "?" in self.path:
(route, params) = self.path.split("?")
else:
route = self.path
params = ""
route = route[1:]
params = params.split("&")
if route in Global.games:
self.send_response(200)
self.end_headers()
self.wfile.write(open(route+'.html', 'rb').read())
elif route == "setScore":
params = {}
for item in self.path.split("?")[1].split("&"):
if "=" in item:
pair = item.split("=")
params[pair[0]] = pair[1]
print(params)
if "imid" in params:
Global.bot.set_game_score(params["uid"], params["score"], inline_message_id=params["imid"])
else:
Global.bot.set_game_score(params["uid"], params["score"], message_id=params["mid"], chat_id=params["cid"])
self.send_response(200)
self.end_headers()
self.wfile.write(b'Set score')
else:
self.send_response(404)
self.end_headers()
self.wfile.write(b'Invalid game!')
def start(update, context):
Global.bot.send_game(update.message.chat_id, Global.featured)
def error(update, context):
print(update, error)
def button(update, context):
print(update)
query = update.callback_query
game = query.game_short_name
uid = str(query.from_user.id)
if query.message:
mid = str(query.message.message_id)
cid = str(query.message.chat.id)
url = "http://" + Global.host + ":"+Global.port + "/" + game + "?uid="+uid+"&mid="+mid+"&cid="+cid
else:
imid = update.callback_query.inline_message_id
url = "http://" + Global.host + ":"+Global.port + "/" + game + "?uid="+uid+"&imid="+imid
print(url)
Global.bot.answer_callback_query(query.id, text=game, url=url)
def inlinequery(update, context):
query = update.inline_query.query
results = []
for game in Global.games:
if query.lower() in game.lower():
results.append(InlineQueryResultGame(id=str(uuid4()),game_short_name=game))
Global.update.inline_query.answer(results)
def main():
config = configparser.ConfigParser()
config.read('config.ini')
token = config['DEFAULT']['API_KEY']
Global.games = config['DEFAULT']['GAMES'].split(',')
Global.host = config['DEFAULT']['HOST']
Global.port = config['DEFAULT']['PORT']
Global.featured = config['DEFAULT']['FEATURED']
updater = Updater(token=token, use_context=True)
dp = updater.dispatcher
dp.add_handler(CommandHandler('start', start))
dp.add_handler(InlineQueryHandler(inlinequery))
dp.add_handler(CallbackQueryHandler(button))
dp.add_error_handler(error)
Global.bot = updater.bot
print("Polling telegram")
updater.start_polling()
print("Starting http server")
http = HTTPServer((Global.host, int(Global.port)), GameHTTPRequestHandler)
http.serve_forever()
if __name__ == '__main__':
main()
HTML5游戏内的代码,与分数相关:
function gameOver() {
isGameOver = true;
clearInterval(gameInterval);
const urlParams = new URLSearchParams(window.location.search);
const uid = urlParams.get('uid');
const mid = urlParams.get('mid');
const cid = urlParams.get('cid');
const imid = urlParams.get('imid');
if (imid) {
const request = new Request(`/setScore?uid=${uid}&imid=${imid}&score=${score}`);
fetch(request).then(response => console.log("set score"));
}
else {
const request = new Request(`/setScore?uid=${uid}&mid=${mid}&cid=${cid}&score=${score}`);
fetch(request).then(response => console.log("set score"));
}
}
Mark Powers 的原始机器人
【问题讨论】:
-
您通常会将 Apache 或 Nginx 之类的东西放在 Python 脚本前面,然后使用该前端工具来终止 ssl。有很多文档展示了如何使用 LetsEncrypt 证书进行配置。
-
对不起,你能解释一下把 Apache 放在我的 Python 脚本前面是什么意思吗?我还在学习,所以我仍然缺乏一些基本概念......如果我这样做了,脚本是否能够执行我在 SimpleHTTTPserver 中使用的 do_get 函数?
-
请尝试澄清相关 HTTP 服务器的连接和机器人功能,例如“让机器人获取分数”到底是什么意思?可能还解释了您如何托管 HTML5 游戏。如果您简要介绍一下您的机器人是如何构建的,这也可能会有所帮助 - 到目前为止,您已经标记了
python和python-telegram-bot,但没有告诉我们您如何使用它们。 -
@CallMeStag 很抱歉我的问题没有更客观,也没有提供代码!最初我想在 Apache 服务器中托管游戏,所以我将 URL 路由到该主机。但是我想不出办法让 Apache 在游戏结束后将分数发送回机器人。如果我将它托管在机器人的同一目录中,使用 SimpleHTTPServer ,该服务器能够将其直接发送到机器人,因此它会显示分数。
-
我知道直接从您的 HTML 游戏(独立于您的机器人托管)发出
set_game_score请求对您来说是一个可以接受的解决方案吗?如果您在 python 中设置了 SimpleHTTPServer:它是否直接监听流量(即发布到 your-domain.org 直接发布到该服务器)或者是否存在例如中间有一些反向代理步骤?
标签: python https telegram telegram-bot python-telegram-bot