Skip to content

Commit

Permalink
Version 1.1.4
Browse files Browse the repository at this point in the history
- Added a documentation XML file
- Updated some variable and method names
- The constructor of YachtsClient had its identity and cache period arguments switched
- Bumped Discord.net for the example project from 3.7.2 to 3.8.0
- Minor general code changes
  • Loading branch information
akacdev committed Sep 7, 2022
1 parent e82e658 commit 4f4ad95
Show file tree
Hide file tree
Showing 7 changed files with 217 additions and 118 deletions.
2 changes: 1 addition & 1 deletion Example/Example.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Discord.Net" Version="3.7.2" />
<PackageReference Include="Discord.Net" Version="3.8.0" />
</ItemGroup>

<ItemGroup>
Expand Down
16 changes: 8 additions & 8 deletions Example/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public static class Program

public static readonly StorageMode Mode = StorageMode.LocalWS;

private static readonly YachtsClient Yachts = new(Mode, 3, "Example Bot");
private static readonly YachtsClient Yachts = new(Mode, "Example Bot", 3);

private static readonly string Token = Environment.GetEnvironmentVariable("BOT_TOKEN");

Expand Down Expand Up @@ -61,9 +61,9 @@ public static async Task Main()

public static async Task Ready()
{
await Logger.Log("Bot", $"Bot is ready to protect your server from {await Yachts.DatabaseSize()} phishing domains", LogSeverity.Info);
await Logger.Log("Bot", $"Ready to protect your server from {await Yachts.GetDatabaseSize()} phishing domains", LogSeverity.Info);

Change[] changes = await Yachts.Recent(TimeSpan.FromDays(1));
Change[] changes = await Yachts.GetRecent(TimeSpan.FromDays(1));

int added = changes.Count(x => x.Type == ChangeType.Add);
int deleted = changes.Count(x => x.Type == ChangeType.Delete);
Expand All @@ -78,11 +78,11 @@ public static async Task OnMessageReceived(SocketMessage msg)
if (msg.Channel is not SocketTextChannel) return;
if (msg.Author.IsBot) return;

if (await Yachts.IsPhishing(msg.Content))
{
await msg.DeleteAsync();
await msg.Channel.SendMessageAsync("Phishing links are not allowed.");
}
bool isPhishing = await Yachts.IsPhishing(msg.Content);
if (!isPhishing) return;

await msg.DeleteAsync();
await msg.Channel.SendMessageAsync($"{msg.Author.Mention}, phishing links are not allowed.");
}
}
}
117 changes: 69 additions & 48 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,76 +9,97 @@
</div>

## Usage
This library can be downloaded as the package `SinkingYachts`. The main class is called `YachtsClient`.
Available on NuGet as `SinkingYachts`, methods are available under the public class `YachtsClient`.

https://www.nuget.org/packages/SinkingYachts

## Features
- Made with **.NET 6**
- Fully async
- Access to a Discord-related phishing database of over `13 300` confirmed malicious domains
- Access to a Discord-related phishing database of over `15 500` confirmed malicious domains
- Regex matching of domains and automatic phishing detection
- Different modes for storing and loading phishing domains
- Instant updates through **WebSocket events**
- Domain whitelisting to prevent false positives
- Customizable caching to decrease load
- Domain whitelisting to decrease false positives
- Customizable caching to decrease load

## Example Project
Under the `Example` directory you can find a working demo Discord bot that implements this library.
```rust
07.09. 19:13:59 [Discord] Discord.Net v3.8.0 (API v9)
07.09. 19:13:59 [Gateway] Connecting
07.09. 19:14:01 [Gateway] Connected
07.09. 19:14:02 [Bot] Ready to protect your server from 15601 phishing domains
07.09. 19:14:02 [Bot] Domains added within the past day: 8
07.09. 19:14:02 [Bot] Domains deleted within the past day: 0
07.09. 19:14:02 [Gateway] Ready
```

## Code Samples

### Check message content
```csharp
bool isPhishing = await Yachts.IsPhishing("hello https://hypesquadacademy-apply.ml");
//👉 True
```

### Check a domain
```csharp
bool isPhishing = await Yachts.IsPhishingDomain("warning-selectioneventhype.gq");
//👉 True
```

### Get the latest domains
```csharp
string[] domains = (await Yachts.GetRecent(TimeSpan.FromDays(1))).Where(x => x.Type == ChangeType.Add).SelectMany(x => x.Domains).ToArray();
//👉 steamcommunitysiv.top, wvwww-roblox.com, discord-download.win, steamcoumunity.eu, streamcummonity.com, streamcommunity.org, join-event-hypesquad.com, steamcommunityzowe.top
```

### Get the database size
```csharp
int size = await Yachts.GetDatabaseSize();
//👉 15601
```

## Available methods
- Task<Change[]> `Recent`(TimeSpan time)
- Task<Change[]> `Recent`(int seconds)
- Task<bool> `IsPhishing`(string content)
- Task<bool> `IsPhishingDomain`(string domain)
- Task<int> `DatabaseSize`()
- Task<string[]> `GetPhishingDomains`()
- Task<Change[]> GetRecent(TimeSpan time)
- Task<Change[]> GetRecent(int seconds)
- Task<bool> IsPhishing(string content)
- Task<bool> IsPhishingDomain(string domain)
- Task<int> GetDatabaseSize()
- Task<string[]> GetPhishingDomains()

## Available events (requires `StorageMode.LocalWS`)
- EventHandler\<string> `DomainAdded`
- EventHandler\<string> `DomainDeleted`
- EventHandler\<string> DomainAdded
- EventHandler\<string> DomainDeleted

## Statistics from the past week
| Date | New domains found |
| :---: | :---: |
| 0.0.0 | + `0` |
| 0.0.0 | + `0` |
| 0.0.0 | + `0` |
| 0.0.0 | + `0` |
| 0.0.0 | + `0` |
| 23.06.2022 | + `33` |
| 24.06.2022 | + `24` |
| 31.08.2022 | + `23` |
| 01.09.2022 | + `10` |
| 02.09.2022 | + `23` |
| 03.09.2022 | + `25` |
| 04.09.2022 | + `3` |
| 05.09.2022 | + `18` |
| 06.09.2022 | + `5` |

## Recently flagged domains
```ruby
steamcommunityzivc.top
www-robloxa.com
wwzw-robloxs.com
www-roblox.com.ru
discoradnitro.xyz
hype-squad-vote.gq
www.discordpolicy.repl.co
wmw-roblox.com
hype-events-badges.gq
wwu-roblox.com
discrod-egift.com
steamcommunityzowe.top
sleamtlade-ofler.xyz
vww-roblox.ga
wwwwv-roblox.com
roblox-profiles.gq
```

## Example
Under the `Example` folder you can find a demo Discord bot that implements this library.
```rust
18.06. 20:09:38 [Discord] Discord.Net v3.6.0 (API v9)
18.06. 20:09:38 [Gateway] Connecting
18.06. 20:09:40 [Gateway] Connected
18.06. 20:09:40 [Bot] Bot is ready to protect your server from 13326 phishing domains
18.06. 20:09:40 [Bot] Domains added within the past day: 111
18.06. 20:09:40 [Bot] Domains deleted within the past day: 0
18.06. 20:09:40 [Gateway] Ready
```

## Unknown domains
Found a Discord/Steam phishing domain that isn't yet present in the database? Send it into the `#domain-reports` channel on our Discord server or open an **issue**.
## Missing domains
Found a Discord/Steam phishing domain that isn't yet present in the database? Send it into the `#domain-reports` channel on our Discord server or open an **issue** in this repository.

## Links
Need help, want to discuss phishing or have a suggestion? Feel free to join our Discord server: https://discord.gg/cT6eQjWW8H
## Resources
Need help, want to discuss phishing or have a suggestion? Feel free to join our Discord server: https://discord.gg/d63pvY28HU (temporarily closed)

Official website: https://sinking.yachts<br>
Email: [email protected]<br>
Email: [email protected], [email protected]<br>
GitHub: https://github.com/SinkingYachts<br>
Blog: https://sinking.yachts/blog/<br>
Blog: https://sinking.yachts/blog/<br>
50 changes: 40 additions & 10 deletions SinkingYachts/Connection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,69 @@

namespace SinkingYachts
{
/// <summary>
/// The class for connecting and receiving messages from the real-time WebSocket server.
/// </summary>
public class Connection
{
public const string URL = "wss://phish.sinking.yachts/feed";
public const int ReconnectionInterval = 10000;
/// <summary>
/// The WebSocket URI to connect to.
/// </summary>
public static readonly Uri Feed = new("wss://phish.sinking.yachts/feed");

/// <summary>
/// How long to wait before reconnecting after a connection is lost.
/// </summary>
public const int ReconnectionDelay = 10000;

private ClientWebSocket WS;
private readonly CancellationTokenSource Source = new();

/// <summary>
/// Whether there is currently a connection to the phishing feed.
/// </summary>
public bool Connected = false;

/// <summary>
/// Executes whenever a phishing domain is added into the database.
/// </summary>
public EventHandler<string> DomainAdded;

/// <summary>
/// Executes whenever a phishing domain is removed from the database.
/// </summary>
public EventHandler<string> DomainDeleted;

private readonly string _identity;
private readonly string Identity;

/// <summary>
/// Default constructor for the connection class.
/// </summary>
/// <param name="identity"></param>
public Connection(string identity)
{
_identity = identity;
Identity = identity;

Connect();
}

/// <summary>
/// Connects to the remote WebSocket server to start receiving updates.
/// </summary>
public async void Connect()
{
Connected = false;
WS = new ClientWebSocket();
WS.Options.SetRequestHeader("X-Identity", _identity);
WS.Options.SetRequestHeader("X-Identity", Identity);

try
{
await WS.ConnectAsync(new Uri(URL), Source.Token);
await WS.ConnectAsync(Feed, Source.Token);
}
catch
{
Connected = false;
await Task.Delay(ReconnectionInterval);
await Task.Delay(ReconnectionDelay);
Connect();
return;
}
Expand All @@ -62,8 +89,8 @@ public async void Connect()

WebSocketReceiveResult result = await WS.ReceiveAsync(bytesReceived, Source.Token);
offset += result.Count;
if (result.EndOfMessage)
break;

if (result.EndOfMessage) break;
}
catch { break; };
}
Expand All @@ -72,10 +99,13 @@ public async void Connect()
}

Connected = false;
await Task.Delay(ReconnectionInterval);
await Task.Delay(ReconnectionDelay);
Connect();
}

/// <summary>
/// Called when a WebSocket message is received.
/// </summary>
public void OnMessage(string msg)
{
Change data;
Expand Down
Loading

0 comments on commit 4f4ad95

Please sign in to comment.