Userlist printing
This commit is contained in:
parent
5240b434a3
commit
f658a78c76
@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
import logging
|
import logging
|
||||||
|
import json
|
||||||
|
|
||||||
class AuthenticationError(Exception):
|
class AuthenticationError(Exception):
|
||||||
""" Exception for 401 errors, meaning your token was bad (expired maybe?) """
|
""" Exception for 401 errors, meaning your token was bad (expired maybe?) """
|
||||||
@ -13,6 +14,14 @@ class NotFoundError(Exception):
|
|||||||
"""Exception for 404 errors, meaning whatever you were looking for wasn't found
|
"""Exception for 404 errors, meaning whatever you were looking for wasn't found
|
||||||
(This is rare from the API) """
|
(This is rare from the API) """
|
||||||
|
|
||||||
|
# Given a normal result set for users, find the user by id or return some reasonable default
|
||||||
|
def get_user_or_default(users, id):
|
||||||
|
for u in users:
|
||||||
|
if "id" in u and u["id"] == id:
|
||||||
|
return u
|
||||||
|
return { "id" : id, "username" : "???", "avatar": "0" }
|
||||||
|
|
||||||
|
|
||||||
# Your gateway to the static endpoints for contentapi. It's a context because it needs
|
# Your gateway to the static endpoints for contentapi. It's a context because it needs
|
||||||
# to track stuff like "which api am I contacting" and "which user am I authenticating as (if any)"
|
# to track stuff like "which api am I contacting" and "which user am I authenticating as (if any)"
|
||||||
class ApiContext:
|
class ApiContext:
|
||||||
@ -84,6 +93,18 @@ class ApiContext:
|
|||||||
self.logger.debug("Error from endpoint: %s" % ex)
|
self.logger.debug("Error from endpoint: %s" % ex)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
# Generate a completely ready websocket request (for data). You can write the result directly to the websocket
|
||||||
|
def gen_ws_request(self, type, data = None, id = None):
|
||||||
|
request = {
|
||||||
|
"type" : type
|
||||||
|
}
|
||||||
|
if data:
|
||||||
|
request["data"] = data
|
||||||
|
if id:
|
||||||
|
request["id"] = id
|
||||||
|
return json.dumps(request)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Return info about the current user based on the token. Useful to see if your token is valid
|
# Return info about the current user based on the token. Useful to see if your token is valid
|
||||||
# and who you are
|
# and who you are
|
||||||
|
56
main.py
56
main.py
@ -31,12 +31,14 @@ config = {
|
|||||||
"tokenfile" : ".qcstoken"
|
"tokenfile" : ".qcstoken"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# The command dictionary (only used to display help)
|
||||||
commands = OrderedDict([
|
commands = OrderedDict([
|
||||||
("h", "Help, prints this menu!"),
|
("h", "Help, prints this menu!"),
|
||||||
("s", "Search, find and/or set a room to listen to (one at a time!)"),
|
("s", "Search, find and/or set a room to listen to (one at a time!)"),
|
||||||
("g", "Global userlist, print users using contentapi in general"),
|
("g", "Global userlist, print users using contentapi in general"),
|
||||||
("u", "Userlist, print users in the current room"),
|
("u", "Userlist, print users in the current room"),
|
||||||
("i", "Insert mode, allows you to send a message (pauses messages!)"),
|
("i", "Insert mode, allows you to send a message (pauses messages!)"),
|
||||||
|
("t", "Statistics, see info about runtime"),
|
||||||
("q", "Quit, no warning!")
|
("q", "Quit, no warning!")
|
||||||
])
|
])
|
||||||
|
|
||||||
@ -76,6 +78,7 @@ def main():
|
|||||||
ws.main_config = config
|
ws.main_config = config
|
||||||
ws.current_room = 0
|
ws.current_room = 0
|
||||||
ws.current_room_data = False
|
ws.current_room_data = False
|
||||||
|
ws.ignored = {}
|
||||||
|
|
||||||
# Go out and get the default room if one was provided.
|
# Go out and get the default room if one was provided.
|
||||||
if config["default_room"]:
|
if config["default_room"]:
|
||||||
@ -91,7 +94,6 @@ def main():
|
|||||||
ws.on_close = ws_onclose
|
ws.on_close = ws_onclose
|
||||||
ws.on_message = ws_onmessage
|
ws.on_message = ws_onmessage
|
||||||
|
|
||||||
# connect to the WebSocket server and block until connected
|
|
||||||
ws.run_forever()
|
ws.run_forever()
|
||||||
|
|
||||||
print("Program end")
|
print("Program end")
|
||||||
@ -104,19 +106,20 @@ def ws_onclose(ws):
|
|||||||
def ws_onopen(ws):
|
def ws_onopen(ws):
|
||||||
|
|
||||||
def main_loop():
|
def main_loop():
|
||||||
printstatus = True
|
|
||||||
|
|
||||||
printr(Fore.GREEN + Style.BRIGHT + "\n-- Connected to live updates! --")
|
printr(Fore.GREEN + Style.BRIGHT + "\n-- Connected to live updates! --")
|
||||||
|
|
||||||
if not ws.current_room:
|
if not ws.current_room:
|
||||||
printr(Fore.YELLOW + "* You are not connected to any room! Press 'S' to search for a room! *")
|
printr(Fore.YELLOW + "* You are not connected to any room! Press 'S' to search for a room! *")
|
||||||
|
|
||||||
|
printstatus = True
|
||||||
|
|
||||||
# The infinite input loop! Or something!
|
# The infinite input loop! Or something!
|
||||||
while True:
|
while True:
|
||||||
if printstatus:
|
if printstatus:
|
||||||
print_statusline(ws)
|
print_statusline(ws)
|
||||||
|
|
||||||
printstatus = True # Allow printing the statusline next time
|
printstatus = False # Assume we are not printing the status every time (it's kinda annoying)
|
||||||
ws.pause_output = False # Allow arbitrary output again
|
ws.pause_output = False # Allow arbitrary output again
|
||||||
key = readchar.readkey()
|
key = readchar.readkey()
|
||||||
|
|
||||||
@ -132,32 +135,65 @@ def ws_onopen(ws):
|
|||||||
print(" " + Style.BRIGHT + key + Style.NORMAL + " - " + value)
|
print(" " + Style.BRIGHT + key + Style.NORMAL + " - " + value)
|
||||||
elif key == "s":
|
elif key == "s":
|
||||||
search(ws)
|
search(ws)
|
||||||
|
printstatus = True
|
||||||
elif key == "g":
|
elif key == "g":
|
||||||
print("not yet")
|
ws.send(ws.context.gen_ws_request("userlist", id = "userlist_global"))
|
||||||
elif key == "u":
|
elif key == "u":
|
||||||
if not ws.current_room:
|
if not ws.current_room:
|
||||||
print("You're not in a room! Can't check userlist!")
|
print("You're not in a room! Can't check userlist!")
|
||||||
else:
|
else:
|
||||||
print("not yet")
|
# Just send it out, we have to wait for the websocket handler to get the response
|
||||||
|
ws.send(ws.context.gen_ws_request("userlist", id = "userlist_room_%d" % ws.current_room))
|
||||||
elif key == "i":
|
elif key == "i":
|
||||||
if not ws.current_room:
|
if not ws.current_room:
|
||||||
print("You're not in a room! Can't send messages!")
|
print("You're not in a room! Can't send messages!")
|
||||||
else:
|
else:
|
||||||
print("not yet")
|
print("not yet")
|
||||||
|
printstatus = True
|
||||||
|
elif key == "t":
|
||||||
|
print(" -- Ignored WS Data (normal) --")
|
||||||
|
for key,value in ws.ignored.items():
|
||||||
|
printr(Style.BRIGHT + ("%16s" % key) + (" : %d" % value))
|
||||||
elif key == "q":
|
elif key == "q":
|
||||||
print("Quitting (may take a bit for the websocket to close)")
|
print("Quitting (may take a bit for the websocket to close)")
|
||||||
ws.close()
|
ws.close()
|
||||||
break
|
break
|
||||||
else:
|
|
||||||
printstatus = False
|
|
||||||
|
|
||||||
# create a thread to run the blocking task
|
# create a thread to run the blocking task
|
||||||
thread = threading.Thread(target=main_loop)
|
thread = threading.Thread(target=main_loop)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
|
# Message handler for our websocket; will handle live messages for the room you're listening to and
|
||||||
|
# userlist updates request results, but not much else (for now)
|
||||||
def ws_onmessage(ws, message):
|
def ws_onmessage(ws, message):
|
||||||
pass
|
logging.debug("WSRCV: " + message)
|
||||||
|
result = json.loads(message)
|
||||||
|
|
||||||
|
# Someone asked for the userlist, check the id to figure out what to print and which list to see
|
||||||
|
if result["type"] == "userlist":
|
||||||
|
all_statuses = result["data"]["statuses"]
|
||||||
|
if result["id"] == "userlist_global":
|
||||||
|
usermessage = " -- Global userlist --"
|
||||||
|
statuses = all_statuses["0"] if "0" in all_statuses else {}
|
||||||
|
else: # This is a bad assumption, it should parse the room id out of the id instead (maybe?)
|
||||||
|
usermessage = " -- Userlist for %s -- " % ws.current_room_data["name"]
|
||||||
|
statuses = all_statuses[str(ws.current_room)] if str(ws.current_room) in all_statuses else {}
|
||||||
|
print(usermessage)
|
||||||
|
print_userlist(statuses, result["data"]["objects"]["user"])
|
||||||
|
|
||||||
|
# Track ignored data
|
||||||
|
if result["type"] not in ws.ignored:
|
||||||
|
ws.ignored[result["type"]] = 0
|
||||||
|
ws.ignored[result["type"]] += 1
|
||||||
|
|
||||||
|
# Print the plain userlist given a list of statuses (in a room or otherwise) and a list of user data
|
||||||
|
# (usually provided by whatever gave you the statuses)
|
||||||
|
def print_userlist(statuses, users):
|
||||||
|
for key,value in statuses.items():
|
||||||
|
key = int(key)
|
||||||
|
user = contentapi.get_user_or_default(users,key)
|
||||||
|
# Weird parenthesis are because I was aligning printed data before
|
||||||
|
printr(Style.BRIGHT + " " + ("%s" % (user["username"] + Style.DIM + " #%d" % key)) + Style.RESET_ALL + " - " + value)
|
||||||
|
|
||||||
|
|
||||||
# Loads the config from file into the global config var. If the file
|
# Loads the config from file into the global config var. If the file
|
||||||
@ -245,7 +281,7 @@ def print_statusline(ws):
|
|||||||
room = "'" + (name[:(MAXTITLE - 3)] + '...' if len(name) > MAXTITLE else name) + "'"
|
room = "'" + (name[:(MAXTITLE - 3)] + '...' if len(name) > MAXTITLE else name) + "'"
|
||||||
else:
|
else:
|
||||||
room = Fore.RED + Style.DIM + "NONE" + Style.NORMAL + Fore.BLACK
|
room = Fore.RED + Style.DIM + "NONE" + Style.NORMAL + Fore.BLACK
|
||||||
print(Back.GREEN + Fore.BLACK + "\n " + ws.user_info["username"] + " - " + room + " CTRL: h s g u i q " + Style.RESET_ALL)
|
print(Back.GREEN + Fore.BLACK + "\n " + ws.user_info["username"] + " - " + room + " CTRL: h s g u i t q " + Style.RESET_ALL)
|
||||||
|
|
||||||
# Print and then reset the style
|
# Print and then reset the style
|
||||||
def printr(msg):
|
def printr(msg):
|
||||||
|
Loading…
Reference in New Issue
Block a user