parley.py 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import asyncio
  2. import json
  3. import pysqlite3 as sql
  4. import sanic
  5. app = sanic.Sanic()
  6. DB = sql.connect('samp.db')
  7. CONNECTIONS = {}
  8. def get_backlog(game: str, c=None) -> [(str, str)]:
  9. if c is None:
  10. c = DB.cursor()
  11. c.execute('SELECT c.user, c.content FROM chat c, games g WHERE c.game = g.id AND g.name = ?', [game])
  12. return list(c)
  13. def get_game_id(game: str, c=None) -> int:
  14. if c is None:
  15. c = DB.cursor()
  16. c.execute('SELECT id FROM games WHERE name = ?', [game])
  17. return c.fetchone()[0]
  18. def add_msg(user: str, content: str, game: str, c=None):
  19. if c is None:
  20. c = DB.cursor()
  21. game_id = get_game_id(game, c)
  22. c.execute('INSERT INTO chat (game, user, content) VALUES (?, ?, ?)', [game_id, user, content])
  23. DB.commit()
  24. @app.route("/static/<f>")
  25. async def static(request, f):
  26. return await sanic.response.file('static/{}'.format(f))
  27. @app.route("/")
  28. async def index(request):
  29. return await sanic.response.file('static/index.html')
  30. @app.websocket("/socket")
  31. async def socket(request, ws):
  32. initial = await ws.recv()
  33. config = json.loads(initial)
  34. user = config['user']
  35. game = config['game']
  36. sanic.log.logger.info(f'connected websocket for {user} in game {game}')
  37. if game not in CONNECTIONS:
  38. CONNECTIONS[game] = set()
  39. CONNECTIONS[game].add(ws)
  40. try:
  41. for (author, content) in get_backlog(game):
  42. await ws.send(json.dumps({"author": author, "content": content}))
  43. async for payload in ws:
  44. msg = json.loads(payload)
  45. add_msg(user, msg['content'], game)
  46. for w in CONNECTIONS[game]:
  47. await w.send(json.dumps({"author": user, "content": msg["content"]}))
  48. finally:
  49. sanic.log.logger.info('removing websocket for {}'.format(config['game']))
  50. CONNECTIONS[config['game']].remove(ws)
  51. if __name__ == '__main__':
  52. try:
  53. app.run()
  54. finally:
  55. DB.close()