chat_room.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. """
  2. 聊天室
  3. ^^^^^^^^^^^
  4. 和当前所有在线的人聊天
  5. `Demo地址 <https://pywebio.herokuapp.com/?pywebio_api=chat_room>`_ `源码 <https://github.com/wang0618/PyWebIO/blob/master/demos/chat_room.py>`_
  6. * 使用基于协程的会话
  7. * 使用 `run_async() <pywebio.session.run_async>` 启动后台协程
  8. """
  9. import asyncio
  10. from pywebio import start_server, run_async
  11. from pywebio.input import *
  12. from pywebio.output import *
  13. # 最大消息记录保存
  14. MAX_MESSAGES_CNT = 10 ** 4
  15. chat_msgs = [] # 聊天记录 (name, msg)
  16. online_users = set() # 在线用户 todo 无法统计主动关闭浏览器的用户退出
  17. async def refresh_msg(my_name):
  18. """刷新聊天消息"""
  19. global chat_msgs
  20. last_idx = len(chat_msgs)
  21. while True:
  22. await asyncio.sleep(0.5)
  23. for m in chat_msgs[last_idx:]:
  24. if m[0] != my_name: # 仅刷新其他人的新信息
  25. put_markdown('`%s`: %s' % m)
  26. # 清理聊天记录
  27. if len(chat_msgs) > MAX_MESSAGES_CNT:
  28. chat_msgs = chat_msgs[len(chat_msgs) // 2:]
  29. last_idx = len(chat_msgs)
  30. async def main():
  31. global chat_msgs
  32. set_output_fixed_height(True)
  33. set_title("PyWebIO Chat Room")
  34. put_markdown("""欢迎来到聊天室,你可以和当前所有在线的人聊天\n
  35. 本应用使用不到80行代码实现,源代码[链接](https://github.com/wang0618/PyWebIO/blob/master/demos/chat_room.py)""", lstrip=True)
  36. nickname = await input("请输入你的昵称", required=True,
  37. valid_func=lambda n: '昵称已被使用' if n in online_users or n == '📢' else None)
  38. online_users.add(nickname)
  39. chat_msgs.append(('📢', '`%s`加入聊天室. 当前在线人数 %s' % (nickname, len(online_users))))
  40. put_markdown('`📢`: `%s`加入聊天室. 当前在线人数 %s' % (nickname, len(online_users)))
  41. refresh_task = run_async(refresh_msg(nickname))
  42. while True:
  43. data = await input_group('发送消息', [
  44. input(name='msg', help_text='消息内容支持Markdown 语法', required=True),
  45. actions(name='cmd', buttons=['发送', {'label': '退出', 'type': 'cancel'}])
  46. ])
  47. if data is None:
  48. break
  49. put_markdown('`%s`: %s' % (nickname, data['msg']))
  50. chat_msgs.append((nickname, data['msg']))
  51. online_users.remove(nickname)
  52. refresh_task.close()
  53. chat_msgs.append(('📢', '`%s`退出聊天室. 当前在线人数 %s' % (nickname, len(online_users))))
  54. put_text("你已经退出聊天室")
  55. if not online_users:
  56. chat_msgs = []
  57. if __name__ == '__main__':
  58. start_server(main, debug=True, port=8080)