Отправка сообщения координатору игры csgo из django
Я использую csgo python модуль для получения значения skin float. Он отлично работает в терминале. Но у меня возникла проблема с его использованием в django. Я обнаружил, что он использует gevent, а я не так много о нем знаю. Поэтому я решил изменить подход, так как он блокировал сервер django. Теперь я запускаю django app и csgo gamecoordinator по отдельности.
Подход 1: Использование сокета для отправки и получения:
csgo_gc.py
import json
import logging
import re
import socket
from csgo.client import CSGOClient
from csgo.enums import ECsgoGCMsg
from google.protobuf.json_format import MessageToDict
from steam.client import SteamClient
logging.basicConfig(format='[%(asctime)s] %(levelname)s %(name)s: %(message)s', level=logging.DEBUG)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
username = '###'
password = '###'
client = SteamClient()
client.set_credential_location('D:\\sentry')
cs = CSGOClient(client)
def get_params(inspect_link):
param_pattern = r'^steam://rungame/730/\d{17}/\+csgo_econ_action_preview%20' \
r'(?:S(?P<param_s>.*)|M(?P<param_m>.*))A(?P<param_a>.*)D(?P<param_d>.*)$'
res = re.match(param_pattern, inspect_link)
if res:
res = res.groupdict(default='0')
for k, v in res.items():
res[k] = int(v)
return res
return None
@client.on(client.EVENT_AUTH_CODE_REQUIRED)
def auth_code_prompt(is_2fa, code_mismatch):
if is_2fa:
code = input("Enter 2FA Code: ")
client.login(username, password, two_factor_code=code)
else:
code = input("Enter Email Code: ")
client.login(username, password, auth_code=code)
@client.on('logged_on')
def start_csgo():
cs.launch()
@cs.on('ready')
def gc_ready():
s.bind(('127.0.0.1', 4500))
s.listen(5)
while True:
print('waiting for a connection')
connection, client_address = s.accept()
try:
print('client connected:', client_address)
while True:
data = connection.recv(4096)
if data:
connection.sendall(send_msg_to_gc(data.decode()))
else:
connection.sendall('Invalid Data'.encode())
except socket.error as e:
print(e)
connection.close()
def send_msg_to_gc(inspect_link: str):
params = get_params(inspect_link)
if params:
cs.send(
ECsgoGCMsg.EMsgGCCStrike15_v2_Client2GCEconPreviewDataBlockRequest,
params
)
response, = cs.wait_event(ECsgoGCMsg.EMsgGCCStrike15_v2_Client2GCEconPreviewDataBlockResponse, timeout=5)
if not response:
return '{"error": "Valve Server Didnt Respond"}'.encode()
return json.dumps(MessageToDict(response)).encode()
return '{"error":"Invalid Inspect Link"}'.encode()
def run():
try:
client.login(username, password)
client.run_forever()
except KeyboardInterrupt:
cs.exit()
client.logout()
exit()
if __name__ == '__main__':
run()
views.py
import json
import socket
from django.shortcuts import render
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('127.0.0.1', 4500)
print(f'connecting to {server_address} port ')
sock.connect(server_address)
def send_data(inspect_link: str):
data = ''
try:
sock.sendall(inspect_link.encode())
data = sock.recv(4096).decode()
data = json.loads(data)
print('received: ', data)
except socket.error as e:
print(e)
return data
def main_page(request):
if request.POST:
inspect_link = request.POST['inspect_link']
response = send_data(inspect_link)
if response.get('error'):
return render(request, 'main_page.html', context={'error': response})
return render(request, 'main_page.html', context={'skin_data': response})
return render(request, 'main_page.html')
Но при одновременной отправке нескольких запросов возвращается ответ только на первый запрос.
Подход 2: Использование gevent WSGI Server:
Нашел об этом здесь
csgo_gc.py
import json
import logging
import re
from csgo.client import CSGOClient
from csgo.enums import ECsgoGCMsg
from gevent.pywsgi import WSGIServer
from google.protobuf.json_format import MessageToDict
from steam.client import SteamClient
logging.basicConfig(format='[%(asctime)s] %(levelname)s %(name)s: %(message)s', level=logging.DEBUG)
username = '###'
password = '###'
client = SteamClient()
client.set_credential_location('D:\\sentry')
cs = CSGOClient(client)
def application(env, start_response):
if env['REQUEST_METHOD'] == 'GET':
if env['PATH_INFO'] == '/':
inspect_link = env['QUERY_STRING'].split('=')[1]
response = send_gc_msg(inspect_link)
start_response('200 OK', [('Content-Type', 'application/json')])
return [f'{response}'.encode()]
start_response('404 Not Found', [('Content-Type', 'text/html')])
return [b'<h1>Not Found</h1>']
def get_params(inspect_link):
param_pattern = r'^steam://rungame/730/\d{17}/\+csgo_econ_action_preview%20' \
r'(?:S(?P<param_s>.*)|M(?P<param_m>.*))A(?P<param_a>.*)D(?P<param_d>.*)$'
res = re.match(param_pattern, inspect_link)
if res:
res = res.groupdict(default='0')
for k, v in res.items():
res[k] = int(v)
return res
return None
@client.on(client.EVENT_AUTH_CODE_REQUIRED)
def auth_code_prompt(is_2fa, code_mismatch):
if is_2fa:
code = input("Enter 2FA Code: ")
client.login(username, password, two_factor_code=code)
else:
code = input("Enter Email Code: ")
client.login(username, password, auth_code=code)
@client.on('logged_on')
def start_csgo():
cs.launch()
@cs.on('ready')
def gc_ready():
print("GC READY")
WSGIServer(('127.0.0.1', 8088), application).serve_forever()
print("SERVER READY")
def send_gc_msg(inspect_link: str):
params = get_params(inspect_link)
if params:
cs.send(
ECsgoGCMsg.EMsgGCCStrike15_v2_Client2GCEconPreviewDataBlockRequest,
params
)
response, = cs.wait_event(ECsgoGCMsg.EMsgGCCStrike15_v2_Client2GCEconPreviewDataBlockResponse, timeout=5)
if not response:
return '{"error": "Valve Server Didnt Respond"}'
return json.dumps(MessageToDict(response))
return '{"error":"Invalid Inspect Link"}'
def run():
try:
client.login(username, password)
client.run_forever()
except KeyboardInterrupt:
cs.exit()
client.logout()
exit()
if __name__ == '__main__':
run()
views.py
from django.shortcuts import render
import requests
import json
def send_data(link: str):
data = ''
try:
r = requests.get(f'http://127.0.0.1:8088?inspect_link={link}')
data = r.content.decode()
except Exception as e:
print(e)
return json.loads(data)
def main_page(request):
if request.POST:
inspect_link = request.POST['inspect_link']
response = send_data(inspect_link)
if response.get('error'):
return render(request, 'main_page.html', context={'error': response})
return render(request, 'main_page.html', context={'skin_data': response})
return render(request, 'main_page.html')
Используя это, я могу отправить несколько запросов одновременно, но ответ на первый запрос возвращается каждому пользователю, который отправил запрос в это время.
Есть ли лучший подход для использования и как мне обрабатывать несколько запросов?