using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Threading.Tasks;
using Alpha;
using Alpha.Core.Command;
using Alpha.Core.Util;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Fomo;
using Fomo.Core;
using FomoChatLog.Commands;
using FomoChatLog.Core;
using FomoChatLog.Sinks;
using Microsoft.CodeAnalysis;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("AndrewLin")]
[assembly: AssemblyConfiguration("Publish")]
[assembly: AssemblyDescription("FomoChatLog: A Fomo submod that logs On-Together chat messages to a local text file. Use /fomohelp and look for /fomochatlog commands")]
[assembly: AssemblyFileVersion("1.2.9.0")]
[assembly: AssemblyInformationalVersion("1.2.9+93bf6c254192ca3bde9494f062dab68782362cda")]
[assembly: AssemblyProduct("AndrewLin.FomoChatLog")]
[assembly: AssemblyTitle("AndrewLin.FomoChatLog")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/andrewlimforfun/ot-mods")]
[assembly: AssemblyVersion("1.2.9.0")]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
}
namespace FomoChatLog
{
public static class BuildInfo
{
public const string Version = "1.2.9";
}
[BepInPlugin("com.andrewlin.ontogether.fomochatlog", "FomoChatLog", "1.2.9")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class FomoChatLogPlugin : BaseUnityPlugin
{
public const string ModGUID = "com.andrewlin.ontogether.fomochatlog";
public const string ModName = "FomoChatLog";
public const string ModVersion = "1.2.9";
private static readonly string DefaultChatLogPathRaw = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "on-together/fomo/on_together_chat_log.txt");
internal static ManualLogSource Log = null;
public static ConfigEntry<bool>? EnableFeature { get; private set; }
private static ConfigEntry<string>? ChatLogPathRaw { get; set; }
public static ConfigEntry<int>? MaxLogDays { get; private set; }
public static ConfigEntry<string>? MessageFormat { get; private set; }
public static ConfigEntry<string>? NotificationFormat { get; private set; }
public static ChatLogManager ChatLog { get; private set; } = null;
private void Awake()
{
Log = ((BaseUnityPlugin)this).Logger;
Log.LogInfo((object)"FomoChatLog v1.2.9 loading…");
InitConfig();
ChatLog = new ChatLogManager(Log, EnableFeature, ChatLogPathRaw, MaxLogDays);
ChatLog.Initialize();
ChatSinkManager sinkManager = FomoPlugin.SinkManager;
if (sinkManager != null)
{
sinkManager.Register((IChatSink)(object)new LogFileChatSink());
}
Log.LogInfo((object)"LogFileChatSink registered with Fomo SinkManager.");
ChatCommandManager commandManager = AlphaPlugin.CommandManager;
if (commandManager != null)
{
commandManager.Register((IChatCommand)(object)new FomoChatLogGetPathCommand());
}
ChatCommandManager commandManager2 = AlphaPlugin.CommandManager;
if (commandManager2 != null)
{
commandManager2.Register((IChatCommand)(object)new FomoChatLogSetPathCommand());
}
ChatCommandManager commandManager3 = AlphaPlugin.CommandManager;
if (commandManager3 != null)
{
commandManager3.Register((IChatCommand)(object)new FomoChatLogToggleCommand());
}
ChatCommandManager commandManager4 = AlphaPlugin.CommandManager;
if (commandManager4 != null)
{
commandManager4.Register((IChatCommand)(object)new FomoChatLogMessageFormatCommand());
}
ChatCommandManager commandManager5 = AlphaPlugin.CommandManager;
if (commandManager5 != null)
{
commandManager5.Register((IChatCommand)(object)new FomoChatLogNotificationFormatCommand());
}
Log.LogInfo((object)"FomoChatLog loaded.");
}
private void InitConfig()
{
EnableFeature = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableFeature", true, "Enable or disable chat file logging.");
ChatLogPathRaw = ((BaseUnityPlugin)this).Config.Bind<string>("General", "ChatLogPath", DefaultChatLogPathRaw, "Base path for chat log files. Supports ~ and environment variables.\nThe date (yyyy-MM-dd) is appended automatically before the file extension.");
MaxLogDays = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxLogDays", 5, "Number of daily log files to retain. Older files are deleted on startup.");
MessageFormat = ((BaseUnityPlugin)this).Config.Bind<string>("Formatting", "MessageFormat", "[{timestamp:yyyy-MM-dd HH:mm:ss}] [{channel}] {username}: {message}", "Format string for chat messages sent to Telegram.\nPlaceholders: {timestamp[:fmt]}, {channel[:short]}, {username}, {message}, {distance}, {source}, {playerid}");
NotificationFormat = ((BaseUnityPlugin)this).Config.Bind<string>("Formatting", "NotificationFormat", "[{timestamp:yyyy-MM-dd HH:mm:ss}] {message}", "Format string for system notifications sent to Telegram.\nPlaceholders: {timestamp[:fmt]}, {channel[:short]}, {username}, {message}, {distance}, {source}, {playerid}");
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "AndrewLin.FomoChatLog";
public const string PLUGIN_NAME = "AndrewLin.FomoChatLog";
public const string PLUGIN_VERSION = "1.2.9";
}
}
namespace FomoChatLog.Sinks
{
public class LogFileChatSink : IChatSink
{
private readonly ManualLogSource _log = Logger.CreateLogSource("FomoChatLog.LFCS");
private const int WarnLimit = 20;
private int _warnCount = 0;
public async Task SendAsync(ChatEntry entry)
{
ConfigEntry<bool>? enableFeature = FomoChatLogPlugin.EnableFeature;
if (enableFeature == null || !enableFeature.Value)
{
return;
}
try
{
string logPath = FomoChatLogPlugin.ChatLog.GetTodayPath();
string format = ((!entry.IsNotification) ? FomoChatLogPlugin.MessageFormat?.Value : FomoChatLogPlugin.NotificationFormat?.Value);
string line = ChatEntryFormatter.Format(entry, format);
await File.AppendAllTextAsync(logPath, line + Environment.NewLine);
}
catch (Exception ex)
{
_warnCount++;
if (_warnCount <= 20)
{
_log.LogWarning((object)("Failed to write chat log: " + ex.Message));
}
else if (_warnCount == 21)
{
_log.LogWarning((object)"Further warnings about chat log writing will be suppressed.");
}
}
}
}
}
namespace FomoChatLog.Core
{
public class ChatLogManager
{
private readonly ManualLogSource _log;
private readonly ConfigEntry<bool> _enableFeature;
private readonly ConfigEntry<string> _pathRaw;
private readonly ConfigEntry<int> _maxLogDays;
public ChatLogManager(ManualLogSource log, ConfigEntry<bool> enableFeature, ConfigEntry<string> pathRaw, ConfigEntry<int> maxLogDays)
{
_log = log;
_enableFeature = enableFeature;
_pathRaw = pathRaw;
_maxLogDays = maxLogDays;
}
public void Initialize()
{
string todayPath = GetTodayPath();
string text = Path.GetDirectoryName(todayPath) ?? string.Empty;
_log.LogInfo((object)("Creating chat log directory if it doesn't exist: " + text));
Directory.CreateDirectory(text);
if (_enableFeature.Value)
{
PruneOldLogs(text);
}
}
public string GetTodayPath()
{
string path = ExpandRaw(_pathRaw.Value);
string path2 = Path.GetDirectoryName(path) ?? string.Empty;
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
string extension = Path.GetExtension(path);
return Path.Combine(path2, $"{fileNameWithoutExtension}_{DateTime.Now:yyyy-MM-dd}{extension}");
}
public void SetBasePath(string newPath)
{
_pathRaw.Value = newPath;
}
private void PruneOldLogs(string dir)
{
string path = ExpandRaw(_pathRaw.Value);
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
string extension = Path.GetExtension(path);
string[] files = Directory.GetFiles(dir, fileNameWithoutExtension + "_????-??-??" + extension);
Array.Sort(files);
int num = files.Length - _maxLogDays.Value;
for (int i = 0; i < num; i++)
{
_log.LogInfo((object)("Pruning old chat log: " + files[i]));
File.Delete(files[i]);
}
}
private static string ExpandRaw(string raw)
{
raw = Environment.ExpandEnvironmentVariables(raw);
if (raw.StartsWith("~"))
{
string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
string text = raw;
raw = Path.Combine(folderPath, text.Substring(1, text.Length - 1));
}
return raw;
}
}
}
namespace FomoChatLog.Commands
{
public class FomoChatLogGetPathCommand : IChatCommand, IComparable<IChatCommand>
{
public const string CMD = "fomochatloggetpath";
public string Name => "fomochatloggetpath";
public string ShortName => "fclgp";
public string Description => "Get the current chat log file path.";
public string Namespace => "fomo";
public void Execute(string[] args)
{
ChatUtils.AddGlobalNotification("Chat log path: " + FomoChatLogPlugin.ChatLog.GetTodayPath());
}
}
public class FomoChatLogMessageFormatCommand : IChatCommand, IComparable<IChatCommand>
{
public const string CMD = "fomochatlogmessageformat";
public string Name => "fomochatlogmessageformat";
public string ShortName => "fclmf";
public string Description => "Set or get the chat log message format.";
public string Namespace => "fomo";
public void Execute(string[] args)
{
ConfigEntry<bool>? enableFeature = FomoChatLogPlugin.EnableFeature;
if (enableFeature == null || !enableFeature.Value)
{
ChatUtils.AddGlobalNotification("Chat log feature is disabled.");
}
else if (FomoChatLogPlugin.MessageFormat == null)
{
ChatUtils.AddGlobalNotification("Fomo Chat Log Mod is not initialized yet.");
}
else if (args.Length == 0)
{
ChatUtils.AddGlobalNotification("Chat log message format: " + FomoChatLogPlugin.MessageFormat?.Value);
}
else if (args.Length != 0)
{
string text = string.Join(" ", args);
if (string.IsNullOrWhiteSpace(text))
{
ChatUtils.AddGlobalNotification("Please enter a valid chat log message format.");
return;
}
FomoChatLogPlugin.MessageFormat.Value = text;
ChatUtils.AddGlobalNotification("Chat log message format is now set to: " + text + ".");
}
}
}
public class FomoChatLogNotificationFormatCommand : IChatCommand, IComparable<IChatCommand>
{
public const string CMD = "fomochatlognotificationformat";
public string Name => "fomochatlognotificationformat";
public string ShortName => "fclnf";
public string Description => "Set or get the chat log notification format.";
public string Namespace => "fomo";
public void Execute(string[] args)
{
ConfigEntry<bool>? enableFeature = FomoChatLogPlugin.EnableFeature;
if (enableFeature == null || !enableFeature.Value)
{
ChatUtils.AddGlobalNotification("Chat log feature is disabled.");
}
else if (FomoChatLogPlugin.NotificationFormat == null)
{
ChatUtils.AddGlobalNotification("Fomo Chat Log Mod is not initialized yet.");
}
else if (args.Length == 0)
{
ChatUtils.AddGlobalNotification("Chat log notification format: " + FomoChatLogPlugin.NotificationFormat?.Value);
}
else if (args.Length != 0)
{
string text = string.Join(" ", args);
if (string.IsNullOrWhiteSpace(text))
{
ChatUtils.AddGlobalNotification("Please enter a valid chat log notification format.");
return;
}
FomoChatLogPlugin.NotificationFormat.Value = text;
ChatUtils.AddGlobalNotification("Chat log notification format is now set to: " + text + ".");
}
}
}
public class FomoChatLogSetPathCommand : IChatCommand, IComparable<IChatCommand>
{
public const string CMD = "fomochatlogsetpath";
public string Name => "fomochatlogsetpath";
public string ShortName => "fclsp";
public string Description => "Set the chat log file path. Usage: /fomochatlogsetpath <path>. Example: /fomochatlogsetpath C:\\Logs\\chat.log";
public string Namespace => "fomo";
public void Execute(string[] args)
{
if (args.Length < 1)
{
ChatUtils.AddGlobalNotification("Usage: /fomochatlogsetpath <path>. Example: /fomochatlogsetpath C:\\Logs\\chat.log");
return;
}
string text = args[0];
if (string.IsNullOrWhiteSpace(text))
{
ChatUtils.AddGlobalNotification("Please enter a valid path.");
return;
}
FomoChatLogPlugin.ChatLog.SetBasePath(text);
try
{
string text2 = Path.GetDirectoryName(text) ?? string.Empty;
if (!string.IsNullOrEmpty(text2) && !Directory.Exists(text2))
{
Directory.CreateDirectory(text2);
}
}
catch (Exception ex)
{
ChatUtils.AddGlobalNotification("Failed to create directory for the new chat log path: " + ex.Message);
return;
}
ChatUtils.AddGlobalNotification("Chat log path set to: " + text + ". Takes effect on next restart.");
}
}
public class FomoChatLogToggleCommand : IChatCommand, IComparable<IChatCommand>
{
public const string CMD = "fomochatlogtoggle";
public string Name => "fomochatlogtoggle";
public string ShortName => "fclt";
public string Description => "Toggle chat file logging on/off.";
public string Namespace => "fomo";
public void Execute(string[] args)
{
if (FomoChatLogPlugin.EnableFeature != null)
{
FomoChatLogPlugin.EnableFeature.Value = !FomoChatLogPlugin.EnableFeature.Value;
ChatUtils.AddGlobalNotification("Fomo chat log is now " + (FomoChatLogPlugin.EnableFeature.Value ? "enabled" : "disabled") + ".");
}
}
}
}