Compare commits

...

12 Commits

Author SHA1 Message Date
thayol 5162796b74 Merge branch 'main' into python-refactor 2021-06-20 08:18:37 +02:00
thayol c2fc1ffa64 Fixed "desynced" bug 2021-06-20 08:12:28 +02:00
thayol 974fc5788b Added a new script to keep the old for fallback 2021-06-17 22:16:11 +02:00
thayol 310a716304 Introduced shutdown privilege. 2021-06-17 22:10:34 +02:00
thayol e51988a57d Fixed MD formatting. 2021-06-17 22:10:34 +02:00
thayol cbf030028c The starting request is now shown. 2021-06-17 22:10:33 +02:00
thayol db0c440d1c Added a shutdown timer 2021-06-17 22:10:33 +02:00
thayol 44eaa2b086 Added auto-shutdown 2021-06-17 22:10:32 +02:00
thayol d4ba9e3f55 Removed useless code 2021-06-17 22:10:32 +02:00
thayol 7a1c1e09f7 Refactored to "is (not)" 2021-06-17 22:10:31 +02:00
thayol a3dfa05bb2 Removed leftovers from non-TLS 2021-06-17 22:10:31 +02:00
thayol 7bf7b0c656 Updated README 2021-06-17 22:10:30 +02:00
15 changed files with 956 additions and 59 deletions
+2 -6
View File
@@ -1,5 +1,4 @@
<?php <?php
// http://zovguran.net/Unalike/API
include "../api_key.php"; include "../api_key.php";
if (!empty($_GET["username"]) || !empty($_GET["userid"])) if (!empty($_GET["username"]) || !empty($_GET["userid"]))
@@ -26,10 +25,7 @@ if (!empty($_GET["username"]) || !empty($_GET["userid"]))
$id = $_GET["userid"]; $id = $_GET["userid"];
} }
if ($id == "~Unalike") else if ($id != "~Unalike" && $id < 0)
{
}
else if ($id < 0)
{ {
echo "Unauthorized"; echo "Unauthorized";
exit(0); exit(0);
@@ -217,7 +213,7 @@ if (!empty($_GET["username"]) || !empty($_GET["userid"]))
} }
else if ($diffs_redirect) else if ($diffs_redirect)
{ {
header("Location: " . "../f/" . strval($beatmapset)); header("Location: ../f/" . strval($beatmapset));
} }
} }
} }
-1
View File
@@ -1,6 +1,5 @@
<?php <?php
session_start(); session_start();
// http://zovguran.net/Unalike/OAuth/
if (!empty($_GET["error"]) && $_GET["error"] == "access_denied") if (!empty($_GET["error"]) && $_GET["error"] == "access_denied")
{ {
+14 -14
View File
@@ -36,16 +36,16 @@ Even though I doubt this would be easy to develop without a complete rewrite, pu
## Setup ## Setup
1. Clone the source code to a subfolder of your web server. 1. Clone the source code to a subfolder of your web server.
2. Copy the files from `setup_help/` to the root of Unalike. Guide [here][setup-help-guide]. 1. Copy the files from `setup_help/` to the root of Unalike. Guide [here][setup-help-guide].
3. Fill in the missing keys in the newly copied files. 1. Fill in the missing keys in the newly copied files.
4. (Optional) Check the configuration section of unalike.py 1. (Optional) Check the configuration section of unalike.py
5. Set up a URL rewrite rule that makes `path/to/unalike/api/USERNAME/KEY/VALUE` point to `path/to/unalike/API/?username=USERNAME&KEY=VALUE` (You can just rewrite these calls manually if you want to, but using API parameters like this is very user friendly.) 1. Set up a URL rewrite rule that makes `path/to/unalike/api/USERNAME/KEY/VALUE` point to `path/to/unalike/API/?username=USERNAME&KEY=VALUE` (You can just rewrite these calls manually if you want to, but using API parameters like this is very user friendly.)
## Start ## Start
1. Start start.ps1 with powershell. 1. Start start.ps1 with powershell.
2. Start your web service if it is stopped. 1. Start your web service if it is stopped.
*(If it's your first time running start.ps1, the service will start automatically.)* *(If it's your first time running start.ps1, the service will start automatically.)*
@@ -53,15 +53,15 @@ Even though I doubt this would be easy to develop without a complete rewrite, pu
## Usage ## Usage
1. Open the web page you deployed in a web browser. 1. Open the web page you deployed in a web browser.
2. Log in with you osu! account. 1. Log in with you osu! account.
3. Press the "Start" button if Unalike is offline. 1. Press the "Start" button if Unalike is offline.
4. Press the "New lobby" button. 1. Press the "New lobby" button.
5. Make sure your osu! client is open and connected to Bancho. 1. Make sure your osu! client is open and connected to Bancho.
6. Press the "Invite" button next of the newly created lobby. 1. Press the "Invite" button next of the newly created lobby.
7. Press F9 in your osu! client to open Bancho, then click the invite link received. 1. Press F9 in your osu! client to open Bancho, then click the invite link received.
8. Wait for Unalike to give you the Host. 1. Wait for Unalike to give you the Host.
9. Pick a map, then ready up to start playing. 1. Pick a map, then ready up to start playing.
10. After playing, don't forget to press the "Shut down" button to save resources. 1. After playing, don't forget to press the "Shut down" button to save resources.
*(Optionally, you can replace step six with pressing the "Send invites" button.)* *(Optionally, you can replace step six with pressing the "Send invites" button.)*
-4
View File
@@ -1,9 +1,5 @@
<?php <?php
session_start(); session_start();
// http://zovguran.net/Unalike/action/?(a|b|c)
// header("Content-Type: application/json");
// echo json_encode($_GET);
if (!empty($_SESSION["unalike-osu-id"]) && !empty($_SESSION["unalike-osu-username"]) && !empty($_SESSION["unalike-granted"]) && $_SESSION["unalike-granted"] === true) if (!empty($_SESSION["unalike-osu-id"]) && !empty($_SESSION["unalike-osu-username"]) && !empty($_SESSION["unalike-granted"]) && $_SESSION["unalike-granted"] === true)
{ {
-1
View File
@@ -1,6 +1,5 @@
<?php <?php
session_start(); session_start();
// http://zovguran.net/Unalike/async/
$unalike = json_decode(file_get_contents("../unalike.json"), true); $unalike = json_decode(file_get_contents("../unalike.json"), true);
// if (!empty($unalike)) // if (!empty($unalike))
-1
View File
@@ -1,6 +1,5 @@
<?php <?php
session_start(); session_start();
// http://zovguran.net/Unalike/async/
$relative_prefix = "../../lobbies/"; $relative_prefix = "../../lobbies/";
$original_suffix = ".json"; $original_suffix = ".json";
+3 -4
View File
@@ -1,6 +1,5 @@
<?php <?php
session_start(); session_start();
// http://zovguran.net/Unalike/async/
$api_url = "http://localhost:80/Unalike/API"; $api_url = "http://localhost:80/Unalike/API";
@@ -188,10 +187,10 @@ if (isset($_GET["render"]))
{ {
$status = '<span class="positive-color">FC</span>'; $status = '<span class="positive-color">FC</span>';
} }
else // else
{ // {
// $status = '<span class="positive-color">PASS</span>'; // $status = '<span class="positive-color">PASS</span>';
} // }
$mode_text = "?"; $mode_text = "?";
if ($score["game"]["mode"] == "osu") if ($score["game"]["mode"] == "osu")
-1
View File
@@ -1,6 +1,5 @@
<?php <?php
session_start(); session_start();
// http://zovguran.net/Unalike/
$authenticated = false; $authenticated = false;
include "api_key.php"; include "api_key.php";
-1
View File
@@ -1,5 +1,4 @@
<?php <?php
// http://zovguran.net/Unalike/login/
include "../api_key.php"; include "../api_key.php";
$scope = implode("+", [ "identify", "public" ]); $scope = implode("+", [ "identify", "public" ]);
-1
View File
@@ -1,6 +1,5 @@
<?php <?php
session_start(); session_start();
// http://zovguran.net/Unalike/logout
unset($_SESSION["unalike-osu-id"]); unset($_SESSION["unalike-osu-id"]);
unset($_SESSION["unalike-osu-username"]); unset($_SESSION["unalike-osu-username"]);
unset($_SESSION["unalike-granted"]); unset($_SESSION["unalike-granted"]);
+1 -1
View File
@@ -16,7 +16,7 @@ For the sake of readability, I'll list the basic steps here.
## osu! API Authentication ## osu! API Authentication
- Copy `/setup_help/api_key.php` to `/api_key.php` - Copy `/setup_help/api_key.php` to `/api_key.php`
- Change the `$api_key` variable's contents to your `API Key` from the [API Registration][osu-api-v1-url] page. - Change the `$api_key` variable's contents to your "API Key" from the [API Registration][osu-api-v1-url] page.
- Register a new OAuth application in your [profile settings][osu-api-v2-url]. - Register a new OAuth application in your [profile settings][osu-api-v2-url].
- Change the `$client_id`, `$client_secret`, and `$callback_uri` to their given values respectively. - Change the `$client_id`, `$client_secret`, and `$callback_uri` to their given values respectively.
+1
View File
@@ -13,6 +13,7 @@ while($true)
else else
{ {
Write-Host "[Unalike] Starting IRC bot..." Write-Host "[Unalike] Starting IRC bot..."
Write-Host "Request: $content"
Set-Content -Path $file -Value "{}" Set-Content -Path $file -Value "{}"
$flags = "unalike.py" $flags = "unalike.py"
$flagArray = $flags -split " " $flagArray = $flags -split " "
+882
View File
@@ -0,0 +1,882 @@
import sys
import time
import socket
import requests
import string
import random
import json
import math
import msvcrt
import os
from os import path
# CONFIGURATION
# location of the account files
CONFIG_ACCOUNT_PATH = "account.php" # take a look at "setup_help/account.php"
CONFIG_LOCAL_SECRET = "local_secret.php" # take a look at "setup_help/local_secret.php"
# how many seconds should be between commands
CONFIG_IRC_SEND_INTERVAL = 4 # in seconds (3 didn't work sometimes, 7 should always work)
# how many seconds should
CONFIG_COMPOSER_DELAY = 1 # in seconds (wait for osu API to catch up)
# reason of introduction: when two players selected a map at the same time, it created an endless loop
CONFIG_NEW_MAPSET_MIN_DELAY = 10 # in seconds (to prevent looping due to Bancho lag)
# how many lobbies should the script be able to manage (there is a limit by peppy!)
CONFIG_MAX_LOBBIES = 4 # this is the default for normal accounts by peppy
# when a lobby is created, how many people should be able to join
CONFIG_LOBBY_SIZE = 1
# checks per second (Hz) [a range between 0.5 and 4 is recommended, can be any arbitrary number]
CONFIG_POLLING_RATE = 2 # 2 = report to the web api every 0.5 seconds (also affects IRC ping)
# the time after the script will exit itself
CONFIG_INACTIVITY_SHUTDOWN = 10 * 60 # in seconds (if it is too high, weird timeout issues start to appear)
# this will be used in chat messages (can be anything, does not have to point to your Unalike)
CONFIG_UNALIKE_URL = "https://zovguran.net/Unalike/"
# change it to match your location of the Unalike API (does not have to be local, leave out the trailing slash)
CONFIG_UNALIKE_API = "http://localhost:80/Unalike/API"
# change it to match your location of the Unalike Composer (does not have to be local, needs the trailing "/?")
CONFIG_UNALIKE_COMPOSER = "http://localhost:80/Unalike/compose/?"
# where the script will listen for requests from the web
CONFIG_REQUESTS_FILE = "requests.json"
# where the script will tell stuff to the web
CONFIG_REPORTS_FILE = "unalike.json"
# where the script will log the created lobbies
CONFIG_LOBBIES_LOG_FOLDER = "lobbies/"
# the CONFIG_ENCODING used for IRC
CONFIG_ENCODING = "utf-8"
# the size of the socket buffer
CONFIG_BUFFER_SIZE = 16384 # you might need to lower this. the bot should work with as low as 1024
# set to True if you want to use the console to send custom commands
CONFIG_CONSOLE_INPUT = False
# set to True if you want to see what the IRC bot is sending to Bancho
CONFIG_IRC_SEND_ECHO = False
# initializing some variables
server = "irc.ppy.sh"
port = 6667
bot_name = ""
bot_pass = ""
lobby_default_pass = "unset"
local_secret = "unset"
current_shutdown_timer = 0
global_session_admin = ""
# folder structure setup
os.makedirs(CONFIG_LOBBIES_LOG_FOLDER, exist_ok=True)
lines = []
with open(CONFIG_ACCOUNT_PATH, "r") as file:
lines = file.readlines()
for line in lines:
if line.lower().find("server:") != -1:
server = line.split(":")[1].strip()
if line.lower().find("port:") != -1:
port = int(line.split(":")[1].strip())
if line.lower().find("name:") != -1:
bot_name = line.split(":")[1].strip()
if line.lower().find("password:") != -1:
bot_pass = line.split(":")[1].strip()
lines = []
with open(CONFIG_LOCAL_SECRET, "r") as file:
lines = file.readlines()
for line in lines:
if line.lower().find("$local_secret") != -1:
local_secret = line.split("\"")[1].strip()
if bot_name == "" or bot_pass == "":
print(CONFIG_ACCOUNT_PATH + " does not contain login details!")
exit()
irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
irc.connect((server, port))
irc.setblocking(False)
# actually irc_queue but for compatibility...
def irc_send(command, argument1="", argument2="", argument3="", argument4="", argument5="", argument6="", custom_delay="global"):
global global_irc_send_queue, CONFIG_IRC_SEND_INTERVAL
line = command.upper()
if argument1 != "":
line = line + " " + argument1
if argument2 != "":
line = line + " " + argument2
if argument3 != "":
line = line + " " + argument3
if argument4 != "":
line = line + " " + argument4
if argument5 != "":
line = line + " " + argument5
if argument6 != "":
line = line + " " + argument6
line = line + "\r\n"
delay = CONFIG_IRC_SEND_INTERVAL
if custom_delay != "global":
delay = custom_delay
global_irc_send_queue.append({ "line": line, "delay": delay })
def irc_send_real(line, delay):
global irc, CONFIG_ENCODING, current_irc_send_timeout
irc.send(line.encode(CONFIG_ENCODING))
current_irc_send_timeout = delay
if CONFIG_IRC_SEND_ECHO:
print("SEND: " + line)
def irc_send_pm(recipent, message):
irc_send("PRIVMSG", recipent, ":"+message)
def irc_send_links(recipient, channel_id=False):
global managed_lobbies
temp_lobbies = []
counter = 1
if channel_id is not False and channel_id in managed_lobbies:
temp_lobbies.append("[" + "osump://" + str(managed_lobbies[channel_id]["lobby"]) + "/" + str(managed_lobbies[channel_id]["password"]) + " " + str(channel_id) + "]")
counter += 1
else:
for lobby in managed_lobbies:
if "password" in managed_lobbies[lobby]:
temp_lobbies.append("[" + "osump://" + str(managed_lobbies[lobby]["lobby"]) + "/" + str(managed_lobbies[lobby]["password"]) + " Lobby #" + str(counter) + "]")
counter += 1
msg = "No Unalike lobbies are ready!"
if counter > 1:
msg = "[" + CONFIG_UNALIKE_URL + " Unalike > ] invite: " + " ".join(temp_lobbies)
print("Sending invite to: " + recipient)
print("Invite content: " + msg)
irc_send_pm(recipient, msg)
def irc_sync_lobbies_to(originating_channel, beatmapset_id, beatmap_id):
global managed_lobbies, CONFIG_NEW_MAPSET_MIN_DELAY
timestamp_now = math.floor(time.time())
if global_last_mapset_played == beatmapset_id:
print(originating_channel + " tried to sync back the last played map!")
else:
syncAllowed = False
if originating_channel in managed_lobbies and "lastSyncInit" in managed_lobbies[originating_channel]:
if abs(timestamp_now - managed_lobbies[originating_channel]["lastSyncInit"]) > CONFIG_NEW_MAPSET_MIN_DELAY:
managed_lobbies[originating_channel]["lastSyncInit"] = timestamp_now
syncAllowed = True
else:
print(originating_channel + " attempted syncing too frequently!")
elif originating_channel == "WebUI":
syncAllowed = True
if syncAllowed:
for lobby in managed_lobbies:
if lobby != originating_channel and "beatmapset" in managed_lobbies[lobby] and managed_lobbies[lobby]["beatmapset"] != beatmapset_id:
skipSync = False
if "desynced" in managed_lobbies[lobby]:
if managed_lobbies[lobby]["desynced"] is True:
skipSync = True
if not skipSync:
if "channel" in managed_lobbies[lobby]:
print("Bringing " + managed_lobbies[lobby]["channel"] + " to compliance...")
irc_send_pm(managed_lobbies[lobby]["channel"], "!mp map " + str(beatmap_id))
managed_lobbies[lobby]["beatmapset"] = beatmapset_id
managed_lobbies[lobby]["beatmap"] = beatmap_id
else:
print("Attempted to set a non-existent lobby's map...")
else:
print("Skipping " + managed_lobbies[lobby]["channel"] + "... (Reason: desynced)")
else:
print(originating_channel + " does not have a sync property!")
def fix_mp_prefix(channel_id):
if channel_id.find("#") == -1:
channel_id = "#mp_" + channel_id
return channel_id
def irc_close_lobby(channel_id, abandon=False):
global managed_lobbies, lobbies_changed
channel_id = fix_mp_prefix(channel_id)
if not abandon:
irc_send_pm(channel_id, "!mp close")
managed_lobbies.pop(channel_id, None)
if abandon:
print(channel_id + " abandoned!")
else:
print(channel_id + " closed!")
lobbies_changed = True
def irc_start_managing(lobby_channel, lobby_name=False, join=False):
global managed_lobbies, lobbies_changed
lobby_channel = fix_mp_prefix(lobby_channel)
print("Lobby registered: " + lobby_channel)
if join:
print("Joining channel: " + lobby_channel)
irc_send("JOIN", lobby_channel)
if not (lobby_channel in managed_lobbies):
managed_lobbies[lobby_channel] = {}
managed_lobbies[lobby_channel]["channel"] = lobby_channel
if lobby_name is not False:
managed_lobbies[lobby_channel]["name"] = lobby_name
if join:
managed_lobbies[lobby_channel]["skipModeSetup"] = True
lobbies_changed = True
def irc_auth(the_name, the_pass=""):
if the_pass != "":
irc_send("PASS", the_pass, custom_delay=0)
irc_send("NICK", the_name, custom_delay=0)
irc_send("USER", the_name, the_name, the_name, the_name, custom_delay=0)
default_sender = "SERVER"
class Command():
def __init__(self):
global default_sender
self.sender = default_sender
self.raw = ""
self.cmd = ""
self.args = []
self.message = ""
self.channel = ""
def irc_to_Command(lines):
cmds = []
for line in lines:
args_start = 1
has_sender = False
if line.find(":") == 0:
args_start = 2
has_sender = True
expl = line.split(" ")
cmd = Command()
cmd.raw = line
cmd.cmd = expl[args_start-1].upper()
cmd.args = expl[args_start:]
if has_sender:
temp_sender = expl[0][1:]
if temp_sender.find("!") != -1:
temp_sender = temp_sender.split("!")[0]
cmd.sender = temp_sender
if cmd.cmd in [ "PRIVMSG", "001", "332", "372", "375", "376", "401", "403" ]:
cmd.channel = expl[args_start]
if (cmd.cmd in ["401", "403"]):
cmd.channel = expl[args_start+1]
temp_msg = " ".join(expl[(args_start+1):])
if len(temp_msg) > 1:
cmd.message = temp_msg[1:].replace(b'\x01ACTION'.decode(CONFIG_ENCODING), "[STATUS]").replace(b'\x01'.decode(CONFIG_ENCODING), "")
cmds.append(cmd)
return cmds
def irc_read():
global irc, CONFIG_ENCODING, CONFIG_BUFFER_SIZE
text = ""
reading = True
while reading:
remaining = ""
try:
remaining = irc.recv(CONFIG_BUFFER_SIZE).decode(CONFIG_ENCODING, "replace")
except Exception:
pass
if remaining == "":
if (len(text) >= 2 and text[-1] == "\n") or text == "":
reading = False
else:
remaining = remaining.replace("\r\n", "\n") # unstandard bancho fix
text = text + remaining
if text == "":
return []
return [x for x in text.split("\n") if len(x.strip()) > 0]
def reset_lobby_states():
global global_playing, managed_lobbies, lobbies_changed
global_playing = False
for lobby in managed_lobbies:
managed_lobbies[lobby]["ready"] = False
managed_lobbies[lobby]["playing"] = False
lobbies_changed = True
print("Lobby states reset.")
def generate_new_password():
global lobby_default_pass
lobby_default_pass = ''.join(random.choice(string.ascii_letters) for i in range(10))
print("A new default password has been generated.")
if CONFIG_CONSOLE_INPUT:
print("--- HELP ---")
print("")
print("ESC: Quit")
print(" c: Command")
print(" t: Message")
print(" r: Reply (last channel)")
print(" b: Message BanchoBot")
print(" p: Responsivity test")
print(" n: Create lobby (+shift: auto-name)")
print(" s: Send links")
print(" x: Close lobby")
print(" Q: RESET STATES")
print("")
print("")
print("--- START ---")
print("")
with open(CONFIG_REQUESTS_FILE, "w") as json_file:
json.dump({}, json_file)
print("Requests JSON reset.")
with open(CONFIG_REPORTS_FILE, "w") as outfile:
json.dump({}, outfile)
print("Report JSON reset.")
managed_lobbies = {}
lobbies_changed = False
current_mapset = 0
current_mapset_default_beatmap = 0
api_player = ""
global_playing = False
global_rounds_played = 0
global_CONFIG_POLLING_RATE = float(1)/CONFIG_POLLING_RATE
global_last_mapset_played = -5
generate_new_password()
global_authenticated = False
boot_timestamp = math.floor(time.time())
current_irc_send_timeout = 0
global_irc_send_queue = []
print("First password: " + lobby_default_pass)
tick = True
print("Beginning authentication...")
irc_auth(bot_name, bot_pass)
last_channel = "BanchoBot"
running = True
while running:
time.sleep(global_CONFIG_POLLING_RATE)
lines = irc_to_Command(irc_read())
request_json = {}
if path.exists(CONFIG_REQUESTS_FILE):
with open(CONFIG_REQUESTS_FILE, "r") as json_file:
request_json = json.load(json_file)
if len(request_json) > 0:
print("NEW REQUEST:", request_json)
with open(CONFIG_REQUESTS_FILE, "w") as json_file:
json.dump({}, json_file)
for request in request_json:
if "type" in request:
if global_session_admin == "" and "issuer" in request and "username" in request["issuer"]:
global_session_admin = request["issuer"]["username"]
if request["type"] == "invite" and "target" in request:
the_filter = False
if "filter" in request:
the_filter = fix_mp_prefix(request["filter"])
irc_send_links(request["target"].replace(" ", "_"), the_filter)
elif request["type"] == "new_lobby":
if len(managed_lobbies) < CONFIG_MAX_LOBBIES:
lobby_name = "Unalike"
if "name" in request:
lobby_name = request["name"]
irc_send_pm("BanchoBot", "!mp make "+lobby_name)
elif request["type"] == "close" and "target" in request:
irc_close_lobby(request["target"])
elif request["type"] == "set_delay" and "target" in request:
if str(request["target"]).isnumeric() and request["target"] >= 1 and request["target"] <= 7:
CONFIG_IRC_SEND_INTERVAL = float(request["target"])
print("Global delay has been updated: " + str(CONFIG_IRC_SEND_INTERVAL))
elif request["type"] == "results_fetched" and "target" in request:
if request["target"] in managed_lobbies and "finished" in managed_lobbies[request["target"]]:
managed_lobbies[request["target"]]["finished"] = False
lobbies_changed = True
elif request["type"] == "ping" and "target" in request:
channel_id = fix_mp_prefix(request["target"])
if channel_id in managed_lobbies:
print("Pinging " + str(channel_id) + " by request.")
irc_send_pm(channel_id, "[" + CONFIG_UNALIKE_URL + " Unalike > ] Someone pinged this lobby.")
elif request["type"] == "sync_all":
if current_mapset != 0 and current_mapset_default_beatmap != 0:
print("Syncing all lobbies...")
irc_sync_lobbies_to("WebUI", current_mapset, current_mapset_default_beatmap)
elif request["type"] == "register" and "target" in request:
print("Registering lobby: " + str(request["target"]))
irc_start_managing(request["target"], join=True)
elif request["type"] == "shutdown":
if global_session_admin != "" and "issuer" in request and "username" in request["issuer"] and global_session_admin == request["issuer"]["username"]:
running = False
break
for line in lines:
if line.cmd in [ "001" ]:
print(line.message)
global_authenticated = True
elif line.cmd == "PRIVMSG" and line.sender == "BanchoBot":
if line.message.find("Created the tournament match ") != -1:
new_lobby_info = line.message.replace("Created the tournament match https://osu.ppy.sh/mp/", "").split(" ")
lobby_channel = new_lobby_info[0]
lobby_name = " ".join(new_lobby_info[1:])
last_channel = lobby_channel
irc_start_managing(lobby_channel, lobby_name)
elif line.message.find("The match has finished!") != -1 or line.message.find("Aborted the match") != -1:
lobby_channel = line.channel
print(line.channel + " ended.")
if not (lobby_channel in managed_lobbies):
managed_lobbies[lobby_channel] = {}
managed_lobbies[lobby_channel]["ready"] = False
managed_lobbies[lobby_channel]["playing"] = False
managed_lobbies[lobby_channel]["finished"] = True
lobbies_changed = True
elif line.message.find("Match starts in ") != -1 or line.message.find("Good luck, have fun!") != -1:
pass
elif line.message.find(" finished playing (") != -1:
player = line.message.split(" finished playing (")[0]
elif line.message.find("The match has started!") != -1:
lobby_channel = line.channel
print(line.channel + " started.")
if not (lobby_channel in managed_lobbies):
managed_lobbies[lobby_channel] = {}
managed_lobbies[lobby_channel]["playing"] = True
lobbies_changed = True
elif line.message.find("All players are ready") != -1:
lobby_channel = line.channel
print(line.channel + " is ready.")
if not (lobby_channel in managed_lobbies):
managed_lobbies[lobby_channel] = {}
managed_lobbies[lobby_channel]["ready"] = True
lobbies_changed = True
elif line.message.find(" left the game.") != -1:
lobby_channel = line.channel
player = line.message.split(" left the game.")[0]
print(player + " left." + "(" + lobby_channel + ")")
if not (lobby_channel in managed_lobbies):
managed_lobbies[lobby_channel] = {}
managed_lobbies[lobby_channel]["ready"] = False
if not ("players" in managed_lobbies[lobby_channel]):
managed_lobbies[lobby_channel]["players"] = []
managed_lobbies[lobby_channel]["players"].remove(player)
elif line.message.find(" joined in slot ") != -1:
lobby_channel = line.channel
player = line.message.split(" joined in slot ")[0]
print(player + " joined." + "(" + lobby_channel + ")")
temp_api_player = player.replace(" ", "_")
httpRequest = requests.get(CONFIG_UNALIKE_API + "/" + temp_api_player + "/t/test")
if httpRequest.text.find("YES") != -1:
print("New API token provider elected: " + api_player + " -> " + temp_api_player)
api_player = temp_api_player
elif httpRequest.text.find("EXPIRING") != -1:
irc_send_pm(temp_api_player, "Your API key is expiring soon. Please click [" + CONFIG_UNALIKE_URL + " here] to refresh it.")
elif httpRequest.text.find("NO") != -1:
irc_send_pm(temp_api_player, "Your API key has expired. Please click [" + CONFIG_UNALIKE_URL + " here] to refresh it.")
irc_send_pm(lobby_channel, "!mp kick " + player)
else:
irc_send_pm(temp_api_player, "Unalike is having connection issues...")
print("API connection issues for player (unalike-side!): " + player)
if not (lobby_channel in managed_lobbies):
managed_lobbies[lobby_channel] = {}
managed_lobbies[lobby_channel]["ready"] = False
if not ("players" in managed_lobbies[lobby_channel]):
managed_lobbies[lobby_channel]["players"] = []
if len(managed_lobbies[lobby_channel]["players"]) < 1:
irc_send_pm(line.channel, "!mp host " + player) # auto host
managed_lobbies[lobby_channel]["players"].append(player)
elif line.message.find("Changed the match password") != -1:
lobby_channel = line.channel
print("Password set in " + line.channel)
if not (lobby_channel in managed_lobbies):
managed_lobbies[lobby_channel] = {}
managed_lobbies[lobby_channel]["password"] = lobby_default_pass
generate_new_password() # let's hope there won't be any random changes
lobbies_changed = True
elif line.message.find("Changed match settings to ") != -1:
lobby_channel = line.channel
lobby_settings = line.message.replace("Changed match settings to ", "").replace(" slots", "").split(", ") #Changed match settings to 1 slots, HeadToHead, Accuracy
lobby_size = int(lobby_settings[0])
lobby_mode = lobby_settings[1]
lobby_win_condition = lobby_settings[2]
print("New settings in " + line.channel + ":")
print(" Win Condition: " + lobby_win_condition)
print(" Mode: " + lobby_mode)
print(" Size: " + str(lobby_size))
if not (lobby_channel in managed_lobbies):
managed_lobbies[lobby_channel] = {}
managed_lobbies[lobby_channel]["winCondition"] = lobby_win_condition
managed_lobbies[lobby_channel]["mode"] = lobby_mode
managed_lobbies[lobby_channel]["size"] = lobby_size
lobbies_changed = True
elif line.message.find("Changed match host to ") != -1:
pass # already announced, this is a duplicate
elif line.message.find(" became the host.") != -1:
player = line.message.split(" became the host.")[0]
print("Host changed: " + player)
elif (line.message.find("Beatmap changed to:") != -1 or line.message.find("Changed beatmap to ") != -1) and line.message.find("osu.ppy.sh/b/"):
lobby_channel = line.channel
try:
temp = line.message.split("osu.ppy.sh/b/")[1].replace(")", "")
if temp.find(" ") != -1:
temp = temp.split(" ")[0]
beatmap_id = int(temp)
except Exception:
beatmap_id = -1
http_request = requests.get(CONFIG_UNALIKE_API + "/" + api_player + "/y/" + str(beatmap_id))
if (http_request.text.isnumeric()):
beatmapset_id = int(http_request.text)
else:
beatmapset_id = -1
print("Beatmap changed to: " + str(beatmap_id) + " (" + str(beatmapset_id) + ")")
if not (lobby_channel in managed_lobbies):
managed_lobbies[lobby_channel] = {}
managed_lobbies[lobby_channel]["beatmap"] = beatmap_id
managed_lobbies[lobby_channel]["ready"] = False
if beatmapset_id > 0:
managed_lobbies[lobby_channel]["beatmapset"] = beatmapset_id
skipSync = False
if "desynced" in managed_lobbies[lobby_channel]:
if managed_lobbies[lobby_channel]["desynced"] is True:
skipSync = True
if skipSync:
print("Skipping sync of " + str(lobby_channel) + "... (Reason: desynced)")
else:
if current_mapset != beatmapset_id:
print("Syncing other lobbies to the new beatmapset... (" + str(current_mapset) + " previously)")
current_mapset = beatmapset_id
current_mapset_default_beatmap = beatmap_id
irc_sync_lobbies_to(lobby_channel, current_mapset, current_mapset_default_beatmap)
else:
print("The beatmap is a part of the current set.")
lobbies_changed = True
elif line.message.find("Host is changing map...") != -1:
lobby_channel = line.channel
beatmap_id = -2
print("Selecting beatmap...")
if not (lobby_channel in managed_lobbies):
managed_lobbies[lobby_channel] = {}
managed_lobbies[lobby_channel]["beatmap"] = beatmap_id
managed_lobbies[lobby_channel]["ready"] = False
lobbies_changed = True
else:
print("[" + line.channel + "] " + line.sender + ": " + line.message)
elif line.cmd == "PRIVMSG" and line.channel in managed_lobbies:
if len(line.message) >= 1 and line.message[0] == ".":
if line.message == ".close":
irc_close_lobby(line.channel)
elif line.message == ".desync":
managed_lobbies[line.channel]["desynced"] = True
print("Setting " + line.channel + " to desynced mode.")
irc_send_pm(channel_id, "[" + CONFIG_UNALIKE_URL + " Unalike > ] The mapset will not sync while desynced.")
lobbies_changed = True
elif line.message == ".sync":
managed_lobbies[line.channel]["desynced"] = False
print("Setting " + line.channel + " to synced mode.")
irc_send_pm(channel_id, "!mp map " + str(current_mapset_default_beatmap))
lobbies_changed = True
elif line.cmd == "PRIVMSG" and line.sender != "BanchoBot":
print("[" + line.channel + "] " + line.sender + ": " + line.message)
elif line.cmd in [ "401", "403" ]: # 401 = No such nick (bancho bug), 403 = No such channel
irc_close_lobby(line.channel, True) # abandon = don't announce close (don't loop endlessly)
elif line.cmd == "332": # Topic (has game number)
if line.message.find("multiplayer game #") != -1:
temp_topic = line.message.replace(":multiplayer game #", "").split(" ")
lobby_id = int(temp_topic[1])
channel_id = temp_topic[0]
print("Received lobby ID (" + str(lobby_id) + ") for channel " + channel_id + ".")
last_channel = channel_id
if channel_id.find("#") == -1:
channel_id = "#" + channel_id
if not (channel_id in managed_lobbies):
managed_lobbies[channel_id] = {}
managed_lobbies[channel_id]["channel"] = channel_id
managed_lobbies[channel_id]["lobby"] = lobby_id
lobbies_changed = True
elif line.cmd in [ "372", "375", "376", "333", "366", "353" ]:
pass
elif line.cmd == "QUIT":
pass
elif line.cmd in [ "JOIN", "PART" ]:
pass # other bancho messages are more useful
elif not (line.cmd in [ "PING", "MODE" ]):
print("")
print(line.raw)
print(line.sender)
print(line.cmd)
print(" ".join(line.args))
print("")
if line.cmd == "PING":
if len(line.args) >= 1:
irc_send("PONG", line.args[0])
if current_irc_send_timeout > 0:
current_irc_send_timeout -= global_CONFIG_POLLING_RATE
if current_irc_send_timeout < 0:
current_irc_send_timeout = 0
elif len(global_irc_send_queue) > 0:
irc_enqueued_obj = global_irc_send_queue.pop(0)
if "line" in irc_enqueued_obj and "delay" in irc_enqueued_obj:
irc_send_real(irc_enqueued_obj["line"], irc_enqueued_obj["delay"])
if global_authenticated:
temp_output = {}
temp_output["lobbies"] = managed_lobbies
temp_output["playing"] = global_playing
temp_output["apiPlayer"] = api_player
temp_output["roundsPlayed"] = global_rounds_played
temp_output["timestamp"] = math.floor(time.time())
temp_output["shutdownTimer"] = math.floor(CONFIG_INACTIVITY_SHUTDOWN - current_shutdown_timer)
temp_output["boot"] = boot_timestamp
temp_output["delay"] = CONFIG_IRC_SEND_INTERVAL
temp_output["maxLobbies"] = CONFIG_MAX_LOBBIES
temp_output["currentMapset"] = current_mapset
temp_output["sessionAdmin"] = global_session_admin
# uncomment to expose commands to the public
# temp_output["command_queue"] = global_irc_send_queue
with open(CONFIG_REPORTS_FILE, "w") as outfile:
json.dump(temp_output, outfile)
current_shutdown_timer += global_CONFIG_POLLING_RATE
if lobbies_changed:
current_shutdown_timer = 0
lobbies_changed = False
all_ready = True
all_finished = True
if len(managed_lobbies) > 0:
print("Managed lobbies (" + str(len(managed_lobbies)) + "):")
for channel_id in managed_lobbies:
print(" ", managed_lobbies[channel_id])
if not ("configured" in managed_lobbies[channel_id]):
managed_lobbies[channel_id]["configured"] = True
managed_lobbies[channel_id]["ready"] = False
managed_lobbies[channel_id]["playing"] = False
managed_lobbies[channel_id]["channel"] = channel_id
managed_lobbies[channel_id]["match"] = channel_id.replace("#mp_", "")
managed_lobbies[channel_id]["roundsPlayed"] = 0
managed_lobbies[channel_id]["players"] = []
managed_lobbies[channel_id]["finished"] = False
managed_lobbies[channel_id]["desynced"] = False
managed_lobbies[channel_id]["lastSyncInit"] = 0
if not ("skipModeSetup" in managed_lobbies[channel_id]):
managed_lobbies[channel_id]["skipModeSetup"] = False
print("Performing basic setup on " + channel_id + "...")
irc_send_pm(channel_id, "!mp password " + str(lobby_default_pass))
if not managed_lobbies[channel_id]["skipModeSetup"]:
irc_send_pm(channel_id, "!mp set 0 1 " + str(CONFIG_LOBBY_SIZE))
lobbies_changed = True
if managed_lobbies[channel_id]["ready"] is False:
all_ready = False
if managed_lobbies[channel_id]["playing"] is True:
all_finished = False
with open(CONFIG_LOBBIES_LOG_FOLDER + managed_lobbies[channel_id]["match"] + ".json", "w") as json_file:
json.dump(managed_lobbies[channel_id], json_file)
if global_playing:
if all_finished:
print("All lobbies finished playing!")
global_playing = False
for channel_id in managed_lobbies:
managed_lobbies[channel_id]["finished"] = False
# irc_send_pm(channel_id, "No results system yet, but the message works. xD")
global_rounds_played += 1
request_matches = []
for channel_id in managed_lobbies:
if "roundsPlayed" in managed_lobbies[channel_id] and "match" in managed_lobbies[channel_id]:
request_matches.append(str(managed_lobbies[channel_id]["match"]) + ",-1")
composer_url = CONFIG_UNALIKE_COMPOSER + "secret=" + local_secret + "&source=" + ";".join(request_matches) + "&beatmapset=" + str(current_mapset)
print("Finished. Request forwarded to: Unalike Composer")
time.sleep(CONFIG_COMPOSER_DELAY)
requests.get(composer_url)
lobbies_changed = True
else:
if all_ready:
print("All lobbies are ready!")
global_playing = True
global_last_mapset_played = current_mapset
temp_timer = len(managed_lobbies) * CONFIG_IRC_SEND_INTERVAL
for channel_id in managed_lobbies:
managed_lobbies[channel_id]["roundsPlayed"] += 1
irc_send_pm(channel_id, "!mp start " + str(temp_timer))
print("Started " + channel_id + " with a " + str(temp_timer) + " second timer.")
temp_timer = temp_timer - CONFIG_IRC_SEND_INTERVAL
else:
print("No lobbies are managed by Unalike.")
if CONFIG_CONSOLE_INPUT:
if msvcrt.kbhit():
pressed_button = msvcrt.getch()
if pressed_button == b'\x1b': # ESC
print("EXITING APPLICATION")
break
elif pressed_button == b'p': # p
print("Pong!")
elif pressed_button == b'c': # c
print("COMMAND MODE")
temp_input = input("Command: ")
if temp_input.find(" "):
temp_args = temp_input.split()
else:
temp_args = [temp_input, ""]
irc_send(temp_args[0], " ".join(temp_args[1:]))
elif pressed_button == b't': # t
print("MESSAGE MODE")
temp_channel = input("Channel/User: ")
temp_message = input("Message: ")
irc_send_pm(temp_channel, temp_message)
if current_shutdown_timer > CONFIG_INACTIVITY_SHUTDOWN:
print("Shutting down due to inactivity.")
running = False
break
print("")
print("--- END ---")
print("")
print("Starting shutdown process...")
with open(CONFIG_REQUESTS_FILE, "w") as json_file:
json.dump({}, json_file)
print("Requests JSON reset.")
to_close_list = []
for channel_id in managed_lobbies:
to_close_list.append(channel_id)
if CONFIG_IRC_SEND_INTERVAL < 5:
CONFIG_IRC_SEND_INTERVAL = 5
for channel_id in to_close_list:
irc_close_lobby(channel_id)
irc_send("QUIT", custom_delay=0)
time.sleep(CONFIG_IRC_SEND_INTERVAL)
for irc_enqueued_obj in global_irc_send_queue:
if "line" in irc_enqueued_obj and "delay" in irc_enqueued_obj:
irc_send_real(irc_enqueued_obj["line"], irc_enqueued_obj["delay"])
# print("SENT: " + str(irc_enqueued_obj["line"]).replace("\r\n", ""))
time.sleep(irc_enqueued_obj["delay"])
with open(CONFIG_REPORTS_FILE, "w") as outfile:
json.dump({}, outfile)
print("Report JSON reset.")
print("Quit request sent!")
+46 -25
View File
@@ -7,7 +7,7 @@ import random
import json import json
import math import math
import msvcrt import msvcrt
import os.path import os
from os import path from os import path
# CONFIGURATION # CONFIGURATION
@@ -34,8 +34,11 @@ lobby_default_size = 1
# checks per second (Hz) [a range between 0.5 and 4 is recommended, can be any arbitrary number] # checks per second (Hz) [a range between 0.5 and 4 is recommended, can be any arbitrary number]
polling_rate = 2 # 2 = report to the web api every 0.5 seconds (also affects IRC ping) polling_rate = 2 # 2 = report to the web api every 0.5 seconds (also affects IRC ping)
# the time after the script will exit itself
global_shutdown_timer = 10 * 60 # in seconds (if it is too high, weird timeout issues start to appear)
# this will be used in chat messages (can be anything, does not have to point to your Unalike) # this will be used in chat messages (can be anything, does not have to point to your Unalike)
unalike_url = "http://zovguran.net/Unalike/" unalike_url = "https://zovguran.net/Unalike/"
# change it to match your location of the Unalike API (does not have to be local) # change it to match your location of the Unalike API (does not have to be local)
unalike_api = "http://localhost:80/Unalike/API" unalike_api = "http://localhost:80/Unalike/API"
@@ -80,6 +83,10 @@ bot_pass = ""
lobby_default_pass = "unset" lobby_default_pass = "unset"
local_secret = "unset" local_secret = "unset"
current_shutdown_timer = 0
global_session_admin = ""
# folder structure setup # folder structure setup
os.makedirs(lobbies_dir, exist_ok=True) os.makedirs(lobbies_dir, exist_ok=True)
@@ -159,7 +166,7 @@ def irc_send_links(recipient, channel_id=False):
temp_lobbies = [] temp_lobbies = []
counter = 1 counter = 1
if channel_id != False and channel_id in managed_lobbies: if channel_id is not False and channel_id in managed_lobbies:
temp_lobbies.append("[" + "osump://" + str(managed_lobbies[channel_id]["lobby"]) + "/" + str(managed_lobbies[channel_id]["password"]) + " " + str(channel_id) + "]") temp_lobbies.append("[" + "osump://" + str(managed_lobbies[channel_id]["lobby"]) + "/" + str(managed_lobbies[channel_id]["password"]) + " " + str(channel_id) + "]")
counter += 1 counter += 1
else: else:
@@ -198,7 +205,7 @@ def irc_sync_lobbies_to(originating_channel, beatmapset_id, beatmap_id):
if lobby != originating_channel and "beatmapset" in managed_lobbies[lobby] and managed_lobbies[lobby]["beatmapset"] != beatmapset_id: if lobby != originating_channel and "beatmapset" in managed_lobbies[lobby] and managed_lobbies[lobby]["beatmapset"] != beatmapset_id:
skipSync = False skipSync = False
if "desynced" in managed_lobbies[lobby]: if "desynced" in managed_lobbies[lobby]:
if managed_lobbies[lobby]["desynced"] == True: if managed_lobbies[lobby]["desynced"] is True:
skipSync = True skipSync = True
if not skipSync: if not skipSync:
@@ -253,7 +260,7 @@ def irc_start_managing(lobby_channel, lobby_name=False, join=False):
managed_lobbies[lobby_channel] = {} managed_lobbies[lobby_channel] = {}
managed_lobbies[lobby_channel]["channel"] = lobby_channel managed_lobbies[lobby_channel]["channel"] = lobby_channel
if lobby_name != False: if lobby_name is not False:
managed_lobbies[lobby_channel]["name"] = lobby_name managed_lobbies[lobby_channel]["name"] = lobby_name
if join: if join:
managed_lobbies[lobby_channel]["skipModeSetup"] = True managed_lobbies[lobby_channel]["skipModeSetup"] = True
@@ -303,7 +310,7 @@ def irc_to_Command(lines):
cmd.channel = expl[args_start+1] cmd.channel = expl[args_start+1]
temp_msg = " ".join(expl[(args_start+1):]) temp_msg = " ".join(expl[(args_start+1):])
if len(temp_msg) > 1: if len(temp_msg) > 1:
cmd.message = temp_msg[1:].replace(b'\x01ACTION'.decode(encoding), "[STATUS]").replace(b'\x01'.decode(encoding), ""); cmd.message = temp_msg[1:].replace(b'\x01ACTION'.decode(encoding), "[STATUS]").replace(b'\x01'.decode(encoding), "")
cmds.append(cmd) cmds.append(cmd)
@@ -332,8 +339,8 @@ def irc_read():
if text == "": if text == "":
return [] return []
else:
return [x for x in text.split("\n") if len(x.strip()) > 0] return [x for x in text.split("\n") if len(x.strip()) > 0]
def reset_lobby_states(): def reset_lobby_states():
global global_playing, managed_lobbies, lobbies_changed global global_playing, managed_lobbies, lobbies_changed
@@ -416,12 +423,15 @@ while running:
for request in request_json: for request in request_json:
if "type" in request: if "type" in request:
if request["type"] == "invite" and "target" in request: if global_session_admin == "" and "issuer" in request and "username" in request["issuer"]:
filter = False; global_session_admin = request["issuer"]["username"]
if "filter" in request:
filter = fix_mp_prefix(request["filter"])
irc_send_links(request["target"].replace(" ", "_"), filter) if request["type"] == "invite" and "target" in request:
the_filter = False
if "filter" in request:
the_filter = fix_mp_prefix(request["filter"])
irc_send_links(request["target"].replace(" ", "_"), the_filter)
elif request["type"] == "new_lobby": elif request["type"] == "new_lobby":
if len(managed_lobbies) < global_max_lobbies: if len(managed_lobbies) < global_max_lobbies:
lobby_name = "Unalike" lobby_name = "Unalike"
@@ -451,8 +461,10 @@ while running:
print("Registering lobby: " + str(request["target"])) print("Registering lobby: " + str(request["target"]))
irc_start_managing(request["target"], join=True) irc_start_managing(request["target"], join=True)
elif request["type"] == "shutdown": elif request["type"] == "shutdown":
running = False if global_session_admin != "" and "issuer" in request and "username" in request["issuer"] and global_session_admin == request["issuer"]["username"]:
break running = False
break
for line in lines: for line in lines:
if line.cmd in [ "001" ]: if line.cmd in [ "001" ]:
@@ -615,7 +627,7 @@ while running:
skipSync = False skipSync = False
if "desynced" in managed_lobbies[lobby_channel]: if "desynced" in managed_lobbies[lobby_channel]:
if managed_lobbies[lobby_channel]["desynced"] == True: if managed_lobbies[lobby_channel]["desynced"] is True:
skipSync = True skipSync = True
if skipSync: if skipSync:
@@ -717,19 +729,23 @@ while running:
temp_output["playing"] = global_playing temp_output["playing"] = global_playing
temp_output["apiPlayer"] = api_player temp_output["apiPlayer"] = api_player
temp_output["roundsPlayed"] = global_rounds_played temp_output["roundsPlayed"] = global_rounds_played
temp_output["timestamp"] = math.floor(time.time()); temp_output["timestamp"] = math.floor(time.time())
temp_output["boot"] = boot_timestamp; temp_output["shutdownTimer"] = math.floor(global_shutdown_timer - current_shutdown_timer)
temp_output["delay"] = global_irc_send_timeout; temp_output["boot"] = boot_timestamp
temp_output["maxLobbies"] = global_max_lobbies; temp_output["delay"] = global_irc_send_timeout
temp_output["current_mapset"] = current_mapset; temp_output["maxLobbies"] = global_max_lobbies
temp_output["currentMapset"] = current_mapset
temp_output["sessionAdmin"] = global_session_admin
# uncomment to expose commands to the public # uncomment to expose commands to the public
# temp_output["command_queue"] = global_irc_send_queue; # temp_output["command_queue"] = global_irc_send_queue
with open(report_file, "w") as outfile: with open(report_file, "w") as outfile:
json.dump(temp_output, outfile) json.dump(temp_output, outfile)
current_shutdown_timer += global_polling_rate
if lobbies_changed: if lobbies_changed:
current_shutdown_timer = 0
lobbies_changed = False lobbies_changed = False
all_ready = True all_ready = True
all_finished = True all_finished = True
@@ -757,9 +773,9 @@ while running:
irc_send_pm(channel_id, "!mp set 0 1 " + str(lobby_default_size)) irc_send_pm(channel_id, "!mp set 0 1 " + str(lobby_default_size))
lobbies_changed = True lobbies_changed = True
if managed_lobbies[channel_id]["ready"] == False: if managed_lobbies[channel_id]["ready"] is False:
all_ready = False all_ready = False
if managed_lobbies[channel_id]["playing"] == True: if managed_lobbies[channel_id]["playing"] is True:
all_finished = False all_finished = False
with open(lobbies_dir + managed_lobbies[channel_id]["match"] + ".json", "w") as json_file: with open(lobbies_dir + managed_lobbies[channel_id]["match"] + ".json", "w") as json_file:
json.dump(managed_lobbies[channel_id], json_file) json.dump(managed_lobbies[channel_id], json_file)
@@ -777,7 +793,7 @@ while running:
if "roundsPlayed" in managed_lobbies[channel_id] and "match" in managed_lobbies[channel_id]: if "roundsPlayed" in managed_lobbies[channel_id] and "match" in managed_lobbies[channel_id]:
request_matches.append(str(managed_lobbies[channel_id]["match"]) + ",-1") request_matches.append(str(managed_lobbies[channel_id]["match"]) + ",-1")
composer_url = unalike_composer + "secret=" + local_secret + "&source=" + ";".join(request_matches) + "&beatmapset=" + str(current_mapset); composer_url = unalike_composer + "secret=" + local_secret + "&source=" + ";".join(request_matches) + "&beatmapset=" + str(current_mapset)
print("Finished. Request forwarded to: Unalike Composer") print("Finished. Request forwarded to: Unalike Composer")
@@ -825,6 +841,11 @@ while running:
temp_message = input("Message: ") temp_message = input("Message: ")
irc_send_pm(temp_channel, temp_message) irc_send_pm(temp_channel, temp_message)
if current_shutdown_timer > global_shutdown_timer:
print("Shutting down due to inactivity.")
running = False
break
print("") print("")
print("--- END ---") print("--- END ---")
print("") print("")
+9 -1
View File
@@ -132,6 +132,14 @@ function updateUnalikeDisplay(unalikeJson) {
if (unalikeJson.delay) { if (unalikeJson.delay) {
newStatus += "</p><p>Current delay: " + unalikeJson.delay + " seconds between commands. (~" + unalikeJson.delay*4 + " seconds to create a lobby.)"; newStatus += "</p><p>Current delay: " + unalikeJson.delay + " seconds between commands. (~" + unalikeJson.delay*4 + " seconds to create a lobby.)";
} }
if (unalikeJson.shutdownTimer) {
newStatus += "</p><p>If nothing happens, Unalike will shut down in " + unalikeJson.shutdownTimer + " seconds.";
}
if (unalikeJson.sessionAdmin) {
newStatus += "</p><p>" + unalikeJson.sessionAdmin + " was the first to interact with Unalike. Only he/she can shut it down on command.";
}
// dynamicJsonElement = document.getElementById("dynamic-json"); // dynamicJsonElement = document.getElementById("dynamic-json");
// dynamicJsonElement.innerHTML = JSON.stringify(unalikeJson); // dynamicJsonElement.innerHTML = JSON.stringify(unalikeJson);
@@ -238,7 +246,7 @@ function updateUnalikeDisplay(unalikeJson) {
if (lobby.desynced) { if (lobby.desynced) {
stateSymbol = "🔀 (Desynced)"; stateSymbol = "🔀 (Desynced)";
} }
else if (lobby.beatmapset > 0 && lobby.beatmapset != unalikeJson.current_mapset) else if (lobby.beatmapset > 0 && lobby.beatmapset != unalikeJson.currentMapset)
{ {
stateSymbol = "🆘 (Desynced)"; stateSymbol = "🆘 (Desynced)";
} }