Отправка сообщения координатору игры 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')

Используя это, я могу отправить несколько запросов одновременно, но ответ на первый запрос возвращается каждому пользователю, который отправил запрос в это время.

Есть ли лучший подход для использования и как мне обрабатывать несколько запросов?

Вернуться на верх