2022-07-21 12:40:13 +00:00
|
|
|
import functools
|
2022-07-21 12:40:17 +00:00
|
|
|
from json import JSONDecodeError, dumps, loads
|
2022-07-21 12:40:13 +00:00
|
|
|
|
2022-07-21 12:40:11 +00:00
|
|
|
from klein import Klein
|
2022-07-21 12:40:13 +00:00
|
|
|
from twisted.web.server import Request
|
|
|
|
|
|
|
|
import main
|
|
|
|
from modules import userinfo
|
2022-07-21 12:40:17 +00:00
|
|
|
from utils.logging.log import warn
|
2022-07-21 12:40:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
def login_required(func):
|
|
|
|
@functools.wraps(func)
|
|
|
|
def wrapper(self, *args, **kwargs):
|
|
|
|
if isinstance(args[0], Request):
|
|
|
|
request = args[0]
|
|
|
|
apikey = request.getHeader("ApiKey")
|
|
|
|
token = request.getHeader("Token")
|
|
|
|
if not apikey:
|
|
|
|
return "No API key provided"
|
|
|
|
if not token:
|
|
|
|
return "No token provided"
|
|
|
|
if apikey not in main.tokens:
|
|
|
|
return "No such API key"
|
|
|
|
config_token = main.tokens[apikey]
|
|
|
|
if not token == config_token["hello"]:
|
|
|
|
return "Invalid token"
|
|
|
|
counter = config_token["counter"]
|
|
|
|
request.setHeader("Counter", counter)
|
|
|
|
return func(self, *args, **kwargs)
|
|
|
|
|
|
|
|
return wrapper
|
2022-07-21 12:40:11 +00:00
|
|
|
|
|
|
|
|
|
|
|
class API(object):
|
|
|
|
"""
|
|
|
|
Our API webapp.
|
|
|
|
"""
|
|
|
|
|
|
|
|
app = Klein()
|
2022-07-21 12:40:13 +00:00
|
|
|
|
2022-07-21 12:40:17 +00:00
|
|
|
@app.route("/", methods=["GET"])
|
2022-07-21 12:40:13 +00:00
|
|
|
@login_required
|
2022-07-21 12:40:11 +00:00
|
|
|
def hello(self, request):
|
|
|
|
return "Hello"
|
2022-07-21 12:40:13 +00:00
|
|
|
|
2022-07-21 12:40:17 +00:00
|
|
|
@app.route("/who/<query>/", methods=["POST"])
|
2022-07-21 12:40:13 +00:00
|
|
|
@login_required
|
|
|
|
def who(self, request, query):
|
2022-07-21 12:40:17 +00:00
|
|
|
try:
|
|
|
|
data = loads(request.content.read())
|
|
|
|
except JSONDecodeError:
|
|
|
|
return "Invalid JSON"
|
|
|
|
if "query" not in data:
|
|
|
|
return "No query provided"
|
|
|
|
result = userinfo.getWho(data["query"])
|
2022-07-21 12:40:13 +00:00
|
|
|
# Expand the generator
|
|
|
|
return dumps({k: [x for x in v] for k, v in result.items()})
|
|
|
|
|
2022-07-21 12:40:17 +00:00
|
|
|
@app.route("/chans/", methods=["POST"])
|
2022-07-21 12:40:13 +00:00
|
|
|
@login_required
|
2022-07-21 12:40:17 +00:00
|
|
|
def chans(self, request):
|
|
|
|
try:
|
|
|
|
data = loads(request.content.read())
|
|
|
|
except JSONDecodeError:
|
|
|
|
return "Invalid JSON"
|
|
|
|
if "net" not in data:
|
|
|
|
return "No net provided"
|
|
|
|
if "query" not in data:
|
|
|
|
return "No query provided"
|
|
|
|
if not data["query"]:
|
|
|
|
warn(f"No query provided: for chans {data}")
|
|
|
|
return dumps({})
|
|
|
|
result = userinfo.getChansSingle(data["net"], data["query"])
|
|
|
|
if not result:
|
|
|
|
return dumps({})
|
|
|
|
return dumps({"chans": [x for x in result]})
|
2022-07-21 12:40:13 +00:00
|
|
|
|
2022-07-21 12:40:17 +00:00
|
|
|
@app.route("/users/", methods=["POST"])
|
2022-07-21 12:40:13 +00:00
|
|
|
@login_required
|
2022-07-21 12:40:17 +00:00
|
|
|
def users(self, request):
|
|
|
|
try:
|
|
|
|
data = loads(request.content.read())
|
|
|
|
except JSONDecodeError:
|
|
|
|
return "Invalid JSON"
|
|
|
|
if "net" not in data:
|
|
|
|
return "No net provided"
|
|
|
|
if "query" not in data:
|
|
|
|
return "No query provided"
|
|
|
|
if not data["query"]:
|
|
|
|
warn(f"No query provided for users: {data}")
|
|
|
|
return dumps({})
|
|
|
|
result = userinfo.getUsersSingle(data["net"], data["query"])
|
|
|
|
if not result:
|
|
|
|
return dumps({})
|
|
|
|
return dumps({"users": [x for x in result]})
|
|
|
|
|
|
|
|
@app.route("/online/", methods=["POST"])
|
|
|
|
@login_required
|
|
|
|
def online(self, request):
|
|
|
|
try:
|
|
|
|
data = loads(request.content.read())
|
|
|
|
except JSONDecodeError:
|
|
|
|
return "Invalid JSON"
|
|
|
|
if "net" not in data:
|
|
|
|
return "No net provided"
|
|
|
|
if "query" not in data:
|
|
|
|
return "No users provided"
|
|
|
|
if not data["query"]:
|
|
|
|
warn(f"No users provided: for online {data}")
|
|
|
|
return dumps({})
|
|
|
|
net = data["net"]
|
|
|
|
usermap = {}
|
|
|
|
for user in data["query"]:
|
|
|
|
channels = userinfo.getChansSingle(net, [user])
|
|
|
|
if channels:
|
|
|
|
usermap[user] = True
|
|
|
|
else:
|
|
|
|
usermap[user] = False
|
|
|
|
|
|
|
|
return dumps(usermap)
|
2022-07-21 12:40:18 +00:00
|
|
|
|
|
|
|
@app.route("/num_users/", methods=["POST"])
|
|
|
|
@login_required
|
|
|
|
def num_users(self, request):
|
|
|
|
try:
|
|
|
|
data = loads(request.content.read())
|
|
|
|
except JSONDecodeError:
|
|
|
|
return "Invalid JSON"
|
|
|
|
if "net" not in data:
|
|
|
|
return "No net provided"
|
|
|
|
if "query" not in data:
|
|
|
|
return "No users provided"
|
|
|
|
if not data["query"]:
|
|
|
|
warn(f"No chans provided: for online {data}")
|
|
|
|
return dumps({})
|
|
|
|
net = data["net"]
|
|
|
|
results = userinfo.getUserNum(net, data["query"])
|
|
|
|
|
|
|
|
return dumps(results)
|
|
|
|
|
|
|
|
@app.route("/num_chans/", methods=["POST"])
|
|
|
|
@login_required
|
|
|
|
def num_chans(self, request):
|
|
|
|
try:
|
|
|
|
data = loads(request.content.read())
|
|
|
|
except JSONDecodeError:
|
|
|
|
return "Invalid JSON"
|
|
|
|
if "net" not in data:
|
|
|
|
return "No net provided"
|
|
|
|
if "query" not in data:
|
|
|
|
return "No users provided"
|
|
|
|
if not data["query"]:
|
|
|
|
warn(f"No users provided: for online {data}")
|
|
|
|
return dumps({})
|
|
|
|
net = data["net"]
|
|
|
|
results = userinfo.getChanNum(net, data["query"])
|
|
|
|
|
|
|
|
return dumps(results)
|
2022-07-25 17:05:53 +00:00
|
|
|
|
|
|
|
@app.route("/irc/stats/", methods=["POST"])
|
|
|
|
@login_required
|
|
|
|
def irc_stats(self, request):
|
|
|
|
stats = {}
|
|
|
|
numChannels = 0
|
|
|
|
numWhoEntries = 0
|
|
|
|
for i in main.IRCPool.keys():
|
|
|
|
numChannels += len(main.IRCPool[i].channels)
|
|
|
|
numWhoEntries += userinfo.getNumTotalWhoEntries()
|
|
|
|
numRelays = 0
|
|
|
|
for net in main.network.keys():
|
|
|
|
numRelays += len(main.network[net].relays)
|
|
|
|
stats["servers_total_total"] = numRelays
|
|
|
|
stats["servers_total_unique"] = len(main.network.keys())
|
|
|
|
stats["servers_online_total"] = len(main.IRCPool.keys())
|
|
|
|
stats["servers_online_unique"] = len(main.liveNets())
|
|
|
|
stats["channels"] = numChannels
|
|
|
|
stats["records"] = numWhoEntries
|
|
|
|
stats["eventrate"] = main.lastMinuteSample
|
|
|
|
return dumps(stats)
|
|
|
|
|
|
|
|
@app.route("/irc/networks/", methods=["POST"])
|
|
|
|
@login_required
|
|
|
|
def irc_networks(self, request):
|
|
|
|
networks = {}
|
|
|
|
for net in main.network.keys():
|
|
|
|
networks[net] = {
|
|
|
|
"relays": len(main.network[net].relays),
|
|
|
|
"channels": userinfo.getTotalChanNum(net),
|
|
|
|
"records": userinfo.getNumWhoEntries(net),
|
|
|
|
}
|
|
|
|
return dumps(networks)
|