Compare commits

..

10 Commits

Author SHA1 Message Date
thayol c2fc1ffa64 Fixed "desynced" bug 2021-06-20 08:12:28 +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
14 changed files with 74 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 " "
+43 -22
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,7 +339,7 @@ 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():
@@ -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,9 +461,11 @@ 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":
if global_session_admin != "" and "issuer" in request and "username" in request["issuer"] and global_session_admin == request["issuer"]["username"]:
running = False running = False
break break
for line in lines: for line in lines:
if line.cmd in [ "001" ]: if line.cmd in [ "001" ]:
print(line.message) print(line.message)
@@ -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)";
} }