Skip to content

Commit

Permalink
Merge pull request #12 from Initialize-A-Baguette/Discord_Interactive
Browse files Browse the repository at this point in the history
Add discord interactive
  • Loading branch information
mdnpascual committed Apr 23, 2023
2 parents 77d878a + dc6be5c commit 7ac0aa2
Show file tree
Hide file tree
Showing 9 changed files with 236 additions and 17 deletions.
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,18 @@ Lower values means a stricter check but more false positives. Higher values mean
Example: ``` "MiddlebarColorDetectionThreshold": "10.0"``` (default)

Where `double_val` is a the amount of variance that the game will accept as the correct color for the middle bar.
Lower values means a stricter check but more false positives. Higher values means less strict but more false negatives.
Lower values means a stricter check but more false positives. Higher values means less strict but more false negatives.

## Discord Notification
#### `"DiscordHookUrl": "<Discord_webhook_URL>"`
Example: ```"DiscordHookUrl": "https://discordapp.com/api/webhooks/xxxx"```
Default value: ""

Where `Discord_webhook_URL` is a link of discord webhook, which can use to send a notification when bait is running out. How to get a `Discord_webhook_URL` you can see at [here](https://support.discord.com/hc/en-us/articles/228383668). After create a webhook, just simple click on `Copy Webhook URL` and paste the value to the setting.

### If you want the hook mention you when send message
#### `"DiscordUserId": "<Discord_User_Id>"`
Example: ```"DiscordUserId": "123456789"```
Default value: ""

Where `Discord_User_Id` is user id that you want to be mentioned. How to get a `Discord_User_Id` you can see at [here](https://support.discord.com/hc/vi/articles/206346498-Where-can-I-find-my-User-Server-Message-ID-). After getting user id, just simple paste the value to the setting. **Note: Make sure the Id you having is User Id, not Message Id or Channel Id**
105 changes: 105 additions & 0 deletions ToF_Fishing_Bot/Addon/DiscordInteractive/DiscordService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace ToF_Fishing_Bot.Addon.DiscordInteractive;


/// <summary>
/// Contain all interactive function with Discord
/// </summary>
public class DiscordService : IDiscordService
{
private readonly string _hookUrl;
private readonly string? _mentionId;
private readonly HttpClient _httpClient = new();
private readonly DateTime EpochTime = new(1970, 1, 1);

/// <summary>
/// Create an instance of <see cref="DiscordService"/>
/// </summary>
/// <param name="hookUrl">Webhook URL. You can see how to get webhook url at: <see href="https://support.discord.com/hc/en-us/articles/228383668"/></param>
/// <param name="mentionId">Discord user Id.</param>
/// <exception cref="ArgumentException"></exception>
public DiscordService(string hookUrl, string? mentionId = null)
{
if (Uri.IsWellFormedUriString(hookUrl, UriKind.Absolute))
{
var uri = new Uri(hookUrl);
if (!uri.Host.Contains("discord.com", StringComparison.CurrentCultureIgnoreCase))
{
throw new ArgumentException("Discord HookUrl provided is not valid");
}
if (!uri.AbsolutePath.Contains("webhooks", StringComparison.CurrentCultureIgnoreCase))
{
throw new ArgumentException("Discord HookUrl provided is not valid");
}
_hookUrl = hookUrl;

}
else
{
throw new ArgumentException("Discord HookUrl provided is not valid");
}
_mentionId = mentionId;
}

/// <summary>
/// Send message to specific webhook above
/// </summary>
/// <param name="content">Message content</param>
/// <returns></returns>
public Task SendMessage(HookContent content)
{
var postContent = JsonContent.Create(content, new MediaTypeWithQualityHeaderValue("application/json"), new JsonSerializerOptions()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
});
return _httpClient.PostAsync(_hookUrl, postContent);
}

/// <summary>
/// Build a message about ran out of bait
/// </summary>
/// <param name="fishingStartAt">Time that user clicked to Star fishing button, provide it in UTC</param>
/// <returns></returns>
public Task<HookContent> BuildOutOfBaitNotification(DateTime fishingStartAt)
{
var strBuild = new StringBuilder("Hello");
if (!string.IsNullOrEmpty(_mentionId))
{
strBuild.Append($"<@!{_mentionId}>");
}
strBuild.AppendLine(". Thank for using fishing bot.");
strBuild.AppendLine("This program is open source and free to use [here](https://github.com/mdnpascual/ToF-Fishing-Bot).");
var hookContent = new HookContent()
{
Content = strBuild.ToString(),
Embeds = new List<HookEmbedContent>()
{
new HookEmbedContent()
{
Color = 5814783,
Title = "Ran out of bait",
Description = "This message is sent because ran out of bait. Fishing Session detail below:",
Fields = new List<HookEmbedField>()
{
new HookEmbedField("Start at:", $"<t:{(int)(fishingStartAt - EpochTime).TotalSeconds}:f>", true),
new HookEmbedField("End at:", $"<t:{(int)(DateTime.UtcNow - EpochTime).TotalSeconds}:f>", true),
},
}
},
Footer = new HookEmbedFooter()
{
Text = "TOF Fishing Bot"
}
};
return Task.FromResult(hookContent);
}
}
14 changes: 14 additions & 0 deletions ToF_Fishing_Bot/Addon/DiscordInteractive/HookContent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ToF_Fishing_Bot.Addon.DiscordInteractive;

public class HookContent
{
public string Content { get; set; } = string.Empty;
public IList<HookEmbedContent> Embeds { get; set; } = new List<HookEmbedContent>();
public HookEmbedFooter? Footer { get; set; }
}
11 changes: 11 additions & 0 deletions ToF_Fishing_Bot/Addon/DiscordInteractive/HookEmbedContent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System.Collections.Generic;

namespace ToF_Fishing_Bot.Addon.DiscordInteractive;

public class HookEmbedContent
{
public string Title { get; set; }
public string Description { get; set; }
public long Color { get; set; }
public IList<HookEmbedField> Fields { get; set; } = new List<HookEmbedField>();
}
15 changes: 15 additions & 0 deletions ToF_Fishing_Bot/Addon/DiscordInteractive/HookEmbedField.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace ToF_Fishing_Bot.Addon.DiscordInteractive;

public class HookEmbedField
{
public HookEmbedField(string name, string value, bool inline = false)
{
Name = name;
Value = value;
Inline = inline;
}

public string Name { get; set; } = string.Empty;
public string Value { get; set; } = string.Empty;
public bool Inline { get; set; }
}
9 changes: 9 additions & 0 deletions ToF_Fishing_Bot/Addon/DiscordInteractive/HookEmbedFooter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;

namespace ToF_Fishing_Bot.Addon.DiscordInteractive;

public class HookEmbedFooter
{
public string Text { get; set; } = string.Empty;
public DateTime? Timestamp { get; set; }
}
13 changes: 13 additions & 0 deletions ToF_Fishing_Bot/Addon/DiscordInteractive/IDiscordService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ToF_Fishing_Bot.Addon.DiscordInteractive;

public interface IDiscordService
{
public Task SendMessage(HookContent content);
public Task<HookContent> BuildOutOfBaitNotification(DateTime fishingStartAt);
}
65 changes: 49 additions & 16 deletions ToF_Fishing_Bot/FishingThread.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using OpenCvSharp.XImgProc;
using ToF_Fishing_Bot.Addon.DiscordInteractive;
using WindowsInput;

namespace ToF_Fishing_Bot
Expand All @@ -17,6 +19,8 @@ class FishingThread
{
private IAppSettings settings;
public bool isRunning = false;
private DateTime _startTime = DateTime.UtcNow;
private DateTime? _lastResetTime = null;
private InputSimulator InputSimulator;

private System.Windows.Shapes.Rectangle left;
Expand Down Expand Up @@ -57,9 +61,11 @@ class FishingThread

public IntPtr? GameHandle = null;

private IDiscordService discordService;

public FishingThread(
IAppSettings _settings,
System.Windows.Shapes.Rectangle _left,
IAppSettings _settings,
System.Windows.Shapes.Rectangle _left,
System.Windows.Shapes.Rectangle _right,
System.Windows.Controls.Label _cursorLabel,
System.Windows.Controls.Label _middleBarLabel,
Expand Down Expand Up @@ -97,6 +103,20 @@ class FishingThread
middleBarCenterThreshold = settings.MiddlebarColorDetectionThreshold;

screenStateLogger = new ScreenStateLogger();

if (!string.IsNullOrEmpty(_settings.DiscordHookUrl))
{

try
{
_lastResetTime = null;
discordService = new DiscordService(_settings.DiscordHookUrl, _settings.DiscordUserId);
}
catch (ArgumentException e)
{
MessageBox.Show(e.Message, "Discord Hook URL invalid", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}

public void Start()
Expand All @@ -110,9 +130,9 @@ public void Start()
fishStaminaButton.Dispatcher.Invoke(new Action(() =>
{
fishStaminaButton.BorderBrush = new SolidColorBrush(System.Windows.Media.Color.FromArgb(
255,
fishStaminaDetected ? (byte)0 : (byte)255,
fishStaminaDetected ? (byte)255 : (byte)0,
255,
fishStaminaDetected ? (byte)0 : (byte)255,
fishStaminaDetected ? (byte)255 : (byte)0,
0));
}));
playerStaminaButton.Dispatcher.Invoke(new Action(() =>
Expand All @@ -135,6 +155,15 @@ public void Start()
switch (state)
{
case FishingState.NotFishing:
if (discordService != null && _lastResetTime != null && DateTime.UtcNow - _lastResetTime > TimeSpan.FromMinutes(3))
{
var notificationMsgTask = discordService.BuildOutOfBaitNotification(_startTime);
notificationMsgTask.Wait();
var notificationMsg = notificationMsgTask.Result;
var sendMsgTask = discordService.SendMessage(notificationMsg);
sendMsgTask.Wait();
_lastResetTime = null;
}
break;
case FishingState.Fishing:
// HANDLER IS ABOVE
Expand All @@ -155,7 +184,8 @@ public void Start()
switch (state)
{
case FishingState.NotFishing:
if (fishStaminaDetected && playerStaminaDetected) {
if (fishStaminaDetected && playerStaminaDetected)
{
state = FishingState.Fishing;
PlayerStamina_lagCompensationDone = false;
LagCompensationDelay = new DispatcherTimer(DispatcherPriority.Send, dis);
Expand Down Expand Up @@ -212,14 +242,15 @@ public void Start()
ResetDelay.Start();
break;
case FishingState.ResetStart:
// DO NOTHING
_lastResetTime = DateTime.UtcNow;
break;
case FishingState.Reset:
state = FishingState.NotFishing;
break;
}
};
isRunning = true;
_startTime = DateTime.UtcNow;
screenStateLogger.Start();
}

Expand All @@ -244,7 +275,8 @@ private Mat ExtractCroppedFrame(Bitmap image)
Cv2.WaitKey();*/
/*var frame = BitmapConverter.ToMat(OldCapture());*/
return frame;
} else
}
else
{
var bordered = new Bitmap(cropped.Width * 4 + 20, cropped.Height * 4);
using (Graphics g = Graphics.FromImage(bordered))
Expand All @@ -265,8 +297,8 @@ private bool FishStaminaDetector(Bitmap image)
{
System.Drawing.Color pixelColor = image.GetPixel(settings.FishStaminaPoint_X, settings.FishStaminaPoint_Y);
var colorDistance = Math.Sqrt(
Math.Pow(pixelColor.R - settings.FishStaminaColor_R, 2) +
Math.Pow(pixelColor.G - settings.FishStaminaColor_G, 2) +
Math.Pow(pixelColor.R - settings.FishStaminaColor_R, 2) +
Math.Pow(pixelColor.G - settings.FishStaminaColor_G, 2) +
Math.Pow(pixelColor.B - settings.FishStaminaColor_B, 2));
cursorLabel.Dispatcher.Invoke(new Action(() => { cursorLabel.Content = colorDistance.ToString("0.##"); }));
return colorDistance < colorThreshold;
Expand All @@ -289,7 +321,7 @@ private void CenterCursor(double middleBarPos, double fishingCursorPos)
{
if (!DPressed)
{
if(GameHandle != null)
if (GameHandle != null)
{
InputSimulator.Keyboard.KeyUpBackground(GameHandle.Value, WindowsInput.Native.VirtualKeyCode.VK_A);
InputSimulator.Keyboard.KeyDownBackground(GameHandle.Value, WindowsInput.Native.VirtualKeyCode.VK_D);
Expand Down Expand Up @@ -360,6 +392,7 @@ private void CenterCursor(double middleBarPos, double fishingCursorPos)

public void Stop()
{
_lastResetTime = null;
screenStateLogger.Stop();
screenStateLogger = new ScreenStateLogger();
}
Expand Down Expand Up @@ -412,16 +445,16 @@ public double GetMiddleBarAveragePos(Mat frame)
});

return (min_X + max_X) / 2.0;
}
catch(Exception){}
}
catch (Exception) { }
return 0;
}

public double GetFishingCursorPos(Mat frame)
{
// MASK WHITE COLOR
var lowerBoundsColor = new OpenCvSharp.Scalar(225, 225, 225, 255);
var upperBoundsColor = new OpenCvSharp.Scalar(255,255,255,255);
var upperBoundsColor = new OpenCvSharp.Scalar(255, 255, 255, 255);

// GET X POSITION OF FISHING CURSOR
var masked = new Mat();
Expand Down Expand Up @@ -463,15 +496,15 @@ public double GetFishingCursorPos(Mat frame)

return lines[0].Item0;
}
catch (Exception){}
catch (Exception) { }
return 0;
}

public void ClickFishCaptureButton()
{
if (GameHandle != null)
{
InputSimulator.Keyboard.KeyDownBackground(GameHandle.Value, (WindowsInput.Native.VirtualKeyCode) settings.KeyCode_FishCapture);
InputSimulator.Keyboard.KeyDownBackground(GameHandle.Value, (WindowsInput.Native.VirtualKeyCode)settings.KeyCode_FishCapture);
InputSimulator.Mouse.Sleep(25);
InputSimulator.Keyboard.KeyUpBackground(GameHandle.Value, (WindowsInput.Native.VirtualKeyCode)settings.KeyCode_FishCapture);
InputSimulator.Mouse.Sleep(25);
Expand Down
5 changes: 5 additions & 0 deletions ToF_Fishing_Bot/IAppSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,10 @@ public interface IAppSettings
int KeyCode_FishCapture { get; set; }
[DefaultValue(27)]
int KeyCode_DismissFishDialogue{ get; set; }

[DefaultValue("")]
string DiscordHookUrl { get; set; }
[DefaultValue("")]
string DiscordUserId { get; set; } // Put value here if you want the tool mention you
}
}

0 comments on commit 7ac0aa2

Please sign in to comment.