+ Add Time logs
This commit is contained in:
+164
-51
@@ -1,25 +1,142 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
using System.IO;
|
||||
|
||||
[InitializeOnLoad]
|
||||
public static class DiscordSceneNotifier
|
||||
public static class SceneNotifier
|
||||
{
|
||||
private const string WebhookUrl = "https://discord.com/api/webhooks/1486718530765328424/42mP_zYNTEwwBbc_lcuasPbpZppXoC4U14-Pde1YatdxatT5s9vml8lgQXTwAmm0PNe5";
|
||||
// Replace with your Discord webhook URL
|
||||
private static readonly string WebhookUrl = "https://discord.com/api/webhooks/1486718530765328424/42mP_zYNTEwwBbc_lcuasPbpZppXoC4U14-Pde1YatdxatT5s9vml8lgQXTwAmm0PNe5";
|
||||
|
||||
static DiscordSceneNotifier()
|
||||
private static readonly string UserName = Environment.UserName;
|
||||
private static readonly string MachineName = Environment.MachineName;
|
||||
private static readonly HttpClient Http = new HttpClient();
|
||||
|
||||
// Key = full scene path, Value = opened timestamp
|
||||
private static readonly Dictionary<string, DateTime> OpenScenes = new Dictionary<string, DateTime>();
|
||||
|
||||
static SceneNotifier()
|
||||
{
|
||||
EditorSceneManager.sceneOpened += OnSceneOpened;
|
||||
EditorSceneManager.sceneClosed += OnSceneClosed;
|
||||
EditorApplication.quitting += OnEditorQuitting;
|
||||
}
|
||||
|
||||
private static string GetUserName()
|
||||
private static void OnSceneOpened(UnityEngine.SceneManagement.Scene scene, OpenSceneMode mode)
|
||||
{
|
||||
return System.Environment.UserName;
|
||||
if (!IsTrackableScene(scene))
|
||||
return;
|
||||
|
||||
string scenePath = scene.path;
|
||||
DateTime openedAt = DateTime.Now;
|
||||
|
||||
OpenScenes[scenePath] = openedAt;
|
||||
|
||||
string message =
|
||||
$"🚧 **Scene Locked**\n" +
|
||||
$"👤 **{UserName}**\n" +
|
||||
$"💻 **{MachineName}**\n" +
|
||||
$"📁 `{FormatPath(scenePath)}`\n" +
|
||||
$"🕒 Opened: **{FormatDateTime(openedAt)}**";
|
||||
|
||||
_ = SendDiscordMessage(message);
|
||||
}
|
||||
|
||||
private static void OnSceneClosed(UnityEngine.SceneManagement.Scene scene)
|
||||
{
|
||||
if (!IsTrackableScene(scene))
|
||||
return;
|
||||
|
||||
string scenePath = scene.path;
|
||||
DateTime closedAt = DateTime.Now;
|
||||
|
||||
if (OpenScenes.TryGetValue(scenePath, out DateTime openedAt))
|
||||
{
|
||||
TimeSpan duration = closedAt - openedAt;
|
||||
|
||||
string message =
|
||||
$"🔓 **Scene Released**\n" +
|
||||
$"👤 **{UserName}**\n" +
|
||||
$"💻 **{MachineName}**\n" +
|
||||
$"📁 `{FormatPath(scenePath)}`\n" +
|
||||
$"🕒 Opened: **{FormatDateTime(openedAt)}**\n" +
|
||||
$"🕒 Closed: **{FormatDateTime(closedAt)}**\n" +
|
||||
$"⏱ Stayed on scene: **{FormatDuration(duration)}**";
|
||||
|
||||
OpenScenes.Remove(scenePath);
|
||||
_ = SendDiscordMessage(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Safety fallback in case Unity reports a close for a scene we did not track
|
||||
string message =
|
||||
$"🔓 **Scene Released**\n" +
|
||||
$"👤 **{UserName}**\n" +
|
||||
$"💻 **{MachineName}**\n" +
|
||||
$"📁 `{FormatPath(scenePath)}`\n" +
|
||||
$"🕒 Closed: **{FormatDateTime(closedAt)}**\n" +
|
||||
$"⏱ Stayed on scene: **unknown**";
|
||||
|
||||
_ = SendDiscordMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnEditorQuitting()
|
||||
{
|
||||
DateTime quitAt = DateTime.Now;
|
||||
|
||||
if (OpenScenes.Count == 0)
|
||||
{
|
||||
string message =
|
||||
$"❌ **Unity Closed**\n" +
|
||||
$"👤 **{UserName}**\n" +
|
||||
$"💻 **{MachineName}**\n" +
|
||||
$"🕒 Closed Unity: **{FormatDateTime(quitAt)}**\n" +
|
||||
$"📂 No tracked open scenes";
|
||||
|
||||
_ = SendDiscordMessage(message);
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy first so we can safely clear afterward
|
||||
var scenesToRelease = new List<KeyValuePair<string, DateTime>>(OpenScenes);
|
||||
|
||||
foreach (var kvp in scenesToRelease)
|
||||
{
|
||||
string scenePath = kvp.Key;
|
||||
DateTime openedAt = kvp.Value;
|
||||
TimeSpan duration = quitAt - openedAt;
|
||||
|
||||
string message =
|
||||
$"❌ **Unity Closed — Scene Auto-Released**\n" +
|
||||
$"👤 **{UserName}**\n" +
|
||||
$"💻 **{MachineName}**\n" +
|
||||
$"📁 `{FormatPath(scenePath)}`\n" +
|
||||
$"🕒 Opened: **{FormatDateTime(openedAt)}**\n" +
|
||||
$"🕒 Unity closed: **{FormatDateTime(quitAt)}**\n" +
|
||||
$"⏱ Stayed on scene: **{FormatDuration(duration)}**";
|
||||
|
||||
_ = SendDiscordMessage(message);
|
||||
}
|
||||
|
||||
OpenScenes.Clear();
|
||||
}
|
||||
|
||||
private static bool IsTrackableScene(UnityEngine.SceneManagement.Scene scene)
|
||||
{
|
||||
// Prevent false notifications on startup / editor internals / untitled scenes
|
||||
if (string.IsNullOrWhiteSpace(scene.path))
|
||||
return false;
|
||||
|
||||
if (!scene.path.StartsWith("Assets/", StringComparison.OrdinalIgnoreCase))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static string FormatPath(string path)
|
||||
@@ -27,64 +144,60 @@ public static class DiscordSceneNotifier
|
||||
return path.Replace("Assets/", "");
|
||||
}
|
||||
|
||||
private static void OnSceneOpened(UnityEngine.SceneManagement.Scene scene, OpenSceneMode mode)
|
||||
private static string FormatDateTime(DateTime dt)
|
||||
{
|
||||
string user = GetUserName();
|
||||
string path = FormatPath(scene.path);
|
||||
|
||||
string message =
|
||||
$"🚧 **Scene Locked**\n" +
|
||||
$"👤 **{user}**\n" +
|
||||
$"📁 `{path}`";
|
||||
|
||||
SendDiscordMessage(message);
|
||||
return dt.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
}
|
||||
|
||||
private static void OnSceneClosed(UnityEngine.SceneManagement.Scene scene)
|
||||
private static string FormatDuration(TimeSpan duration)
|
||||
{
|
||||
string user = GetUserName();
|
||||
string path = FormatPath(scene.path);
|
||||
if (duration.TotalSeconds < 60)
|
||||
return $"{(int)duration.TotalSeconds}s";
|
||||
|
||||
string message =
|
||||
$"🔓 **Scene Released**\n" +
|
||||
$"👤 **{user}**\n" +
|
||||
$"📁 `{path}`";
|
||||
if (duration.TotalMinutes < 60)
|
||||
return $"{(int)duration.TotalMinutes}m {duration.Seconds}s";
|
||||
|
||||
SendDiscordMessage(message);
|
||||
return $"{(int)duration.TotalHours}h {duration.Minutes}m {duration.Seconds}s";
|
||||
}
|
||||
|
||||
private static void OnEditorQuitting()
|
||||
private static async Task SendDiscordMessage(string content)
|
||||
{
|
||||
string user = GetUserName();
|
||||
try
|
||||
{
|
||||
string escapedContent = EscapeJson(content);
|
||||
string json = $"{{\"content\":\"{escapedContent}\"}}";
|
||||
|
||||
string message =
|
||||
$"❌ **Unity Closed**\n" +
|
||||
$"👤 **{user}**\n" +
|
||||
$"All scenes released";
|
||||
using var httpContent = new StringContent(json, Encoding.UTF8, "application/json");
|
||||
using var response = await Http.PostAsync(WebhookUrl, httpContent);
|
||||
|
||||
SendDiscordMessage(message);
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
Debug.Log($"[SceneNotifier] Sent to Discord:\n{content}");
|
||||
}
|
||||
else
|
||||
{
|
||||
string responseBody = await response.Content.ReadAsStringAsync();
|
||||
Debug.LogWarning(
|
||||
$"[SceneNotifier] Discord webhook failed. Status: {(int)response.StatusCode} {response.StatusCode}\n{responseBody}"
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogWarning($"[SceneNotifier] Failed to notify Discord: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private static async void SendDiscordMessage(string content)
|
||||
private static string EscapeJson(string value)
|
||||
{
|
||||
string json = JsonUtility.ToJson(new DiscordMessage { content = content });
|
||||
if (string.IsNullOrEmpty(value))
|
||||
return string.Empty;
|
||||
|
||||
using var request = new UnityWebRequest(WebhookUrl, "POST");
|
||||
byte[] bodyRaw = Encoding.UTF8.GetBytes(json);
|
||||
|
||||
request.uploadHandler = new UploadHandlerRaw(bodyRaw);
|
||||
request.downloadHandler = new DownloadHandlerBuffer();
|
||||
request.SetRequestHeader("Content-Type", "application/json");
|
||||
|
||||
await request.SendWebRequest();
|
||||
|
||||
if (request.result != UnityWebRequest.Result.Success)
|
||||
Debug.LogWarning("Discord webhook failed: " + request.error);
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
private class DiscordMessage
|
||||
{
|
||||
public string content;
|
||||
return value
|
||||
.Replace("\\", "\\\\")
|
||||
.Replace("\"", "\\\"")
|
||||
.Replace("\r", "\\r")
|
||||
.Replace("\n", "\\n")
|
||||
.Replace("\t", "\\t");
|
||||
}
|
||||
}
|
||||
+5575
-295
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user