parley.py 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  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. res = c.fetchone()
  18. if res is not None:
  19. return res[0]
  20. else:
  21. c.execute('INSERT INTO games (name) VALUES (?)', [game])
  22. DB.commit()
  23. c.execute('SELECT id FROM games WHERE name = ?', [game])
  24. return c.fetchone()[0]
  25. def add_msg(user: str, content: str, game: str, c=None):
  26. if c is None:
  27. c = DB.cursor()
  28. game_id = get_game_id(game, c)
  29. c.execute('INSERT INTO chat (game, user, content) VALUES (?, ?, ?)', [game_id, user, content])
  30. DB.commit()
  31. @app.route("/static/<f>")
  32. async def static(request, f):
  33. return await sanic.response.file('static/{}'.format(f))
  34. @app.route("/")
  35. async def index(request):
  36. return await sanic.response.file('static/index.html')
  37. @app.websocket("/socket")
  38. async def socket(request, ws):
  39. initial = await ws.recv()
  40. config = json.loads(initial)
  41. user = config['user']
  42. game = config['game']
  43. sanic.log.logger.info(f'connected websocket for {user} in game {game}')
  44. if game not in CONNECTIONS:
  45. CONNECTIONS[game] = set()
  46. CONNECTIONS[game].add(ws)
  47. try:
  48. for (author, content) in get_backlog(game):
  49. await ws.send(json.dumps({"author": author, "content": content}))
  50. async for payload in ws:
  51. msg = json.loads(payload)
  52. add_msg(user, msg['content'], game)
  53. for w in CONNECTIONS[game]:
  54. await w.send(json.dumps({"author": user, "content": msg["content"]}))
  55. finally:
  56. sanic.log.logger.info('removing websocket for {}'.format(config['game']))
  57. CONNECTIONS[config['game']].remove(ws)
  58. if __name__ == '__main__':
  59. try:
  60. app.run()
  61. finally:
  62. DB.close()