-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
384 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
version: 2 | ||
updates: | ||
- package-ecosystem: "github-actions" | ||
directory: "/" | ||
schedule: | ||
interval: "weekly" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
name: CI | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
- master | ||
tags: | ||
- '*' | ||
pull_request: | ||
branches: | ||
- main | ||
- master | ||
|
||
jobs: | ||
build: | ||
name: "Build" | ||
runs-on: ${{ matrix.os }} | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
os: [ubuntu-20.04] | ||
include: | ||
- os: ubuntu-20.04 | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- name: Build sourcemod plugin | ||
uses: maxime1907/action-sourceknight@v1 | ||
with: | ||
cmd: build | ||
|
||
- name: Create package | ||
run: | | ||
mkdir -p /tmp/package | ||
cp -R .sourceknight/package/* /tmp/package | ||
- name: Upload build archive for test runners | ||
uses: actions/upload-artifact@v3 | ||
with: | ||
name: package | ||
path: /tmp/package | ||
|
||
tag: | ||
name: Tag | ||
needs: build | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' | ||
|
||
- uses: dev-drprasad/[email protected] | ||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' | ||
with: | ||
delete_release: true | ||
tag_name: latest | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
|
||
- uses: rickstaa/action-create-tag@v1 | ||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' | ||
with: | ||
tag: "latest" | ||
github_token: ${{ secrets.GITHUB_TOKEN }} | ||
|
||
release: | ||
name: Release | ||
if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' | ||
needs: [build, tag] | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Download artifacts | ||
uses: actions/download-artifact@v3 | ||
|
||
- name: Versioning | ||
run: | | ||
version="latest" | ||
if [[ "${{ github.ref_type }}" == 'tag' ]]; then | ||
version=`echo $GITHUB_REF | sed "s/refs\/tags\///"`; | ||
fi | ||
echo "RELEASE_VERSION=$version" >> $GITHUB_ENV | ||
- name: Package | ||
run: | | ||
ls -Rall | ||
if [ -d "./package/" ]; then | ||
cd ./package/ | ||
tar -czf ../${{ github.event.repository.name }}-${{ env.RELEASE_VERSION }}.tar.gz -T <(\ls -1) | ||
cd - | ||
fi | ||
- name: Release | ||
uses: svenstaro/upload-release-action@v2 | ||
with: | ||
repo_token: ${{ secrets.GITHUB_TOKEN }} | ||
file: '*.tar.gz' | ||
tag: ${{ env.RELEASE_VERSION }} | ||
file_glob: true | ||
overwrite: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
build/ | ||
release/ | ||
|
||
.DS_Store | ||
.vscode | ||
|
||
*.smx | ||
plugins/ | ||
.sourceknight | ||
.venv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
# sm-plugin-AntiBhopCheat-discord | ||
sm-plugin-AntiBhopCheat-discord | ||
> [!IMPORTANT] | ||
> Requirement: [sm-plugin-AntiBhopCheat](https://github.com/srcdslab/sm-plugin-AntiBhopCheat) | ||
AntiBhopCheat detections notifications to discord | ||
![Preview](https://i.imgur.com/T2NYkTc.png) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
#include <utilshelper> | ||
#include <discordWebhookAPI> | ||
|
||
#undef REQUIRE_PLUGIN | ||
#tryinclude <SelectiveBhop> | ||
#tryinclude <ExtendedDiscord> | ||
#tryinclude <sourcebanschecker> | ||
#define REQUIRE_PLUGIN | ||
|
||
#define WEBHOOK_MSG_MAX_SIZE 2000 | ||
#define WEBHOOK_URL_MAX_SIZE 1000 | ||
#define WEBHOOK_THREAD_NAME_MAX_SIZE 100 | ||
|
||
ConVar g_cvCountBots, g_cvWebhook, g_cvWebhookRetry, g_cvChannelType; | ||
ConVar g_cvThreadName, g_cvThreadID, g_cvAvatar; | ||
|
||
char g_sMap[PLATFORM_MAX_PATH]; | ||
char g_sPluginName[256]; | ||
bool g_Plugin_SourceBans = false; | ||
bool g_Plugin_ExtDiscord = false; | ||
|
||
public Plugin myinfo = | ||
{ | ||
name = "AntiBhopCheat Discord", | ||
author = ".Rushaway", | ||
description = "Send webhook when a bhop cheat is detected", | ||
version = "1.0.0", | ||
url = "https://github.com/srcdslab/sm-plugin-AntiBhopCheat-discord" | ||
}; | ||
|
||
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) | ||
{ | ||
RegPluginLibrary("AntiBhopCheat_Discord"); | ||
return APLRes_Success; | ||
} | ||
|
||
public void OnPluginStart() | ||
{ | ||
g_cvCountBots = CreateConVar("sm_antibhopcheat_count_bots", "1", "Should we count bots as players ?[0 = No, 1 = Yes]", FCVAR_NOTIFY, true, 0.0, true, 1.0); | ||
g_cvWebhook = CreateConVar("sm_antibhopcheat_discord_webhook", "", "The webhook URL of your Discord channel.", FCVAR_PROTECTED); | ||
g_cvWebhookRetry = CreateConVar("sm_antibhopcheat_discord_webhook_retry", "3", "Number of retries if webhook fails.", FCVAR_PROTECTED); | ||
g_cvAvatar = CreateConVar("sm_antibhopcheat_discord_avatar", "https://avatars.githubusercontent.com/u/110772618?s=200&v=4", "URL to Avatar image."); | ||
g_cvChannelType = CreateConVar("sm_antibhopcheat_discord_channel_type", "0", "Type of your channel: (1 = Thread, 0 = Classic Text channel"); | ||
|
||
/* Thread config */ | ||
g_cvThreadName = CreateConVar("sm_antibhopcheat_discord_threadname", "AntiBhopCheat - New detection", "The Thread Name of your Discord forums. (If not empty, will create a new thread)", FCVAR_PROTECTED); | ||
g_cvThreadID = CreateConVar("sm_antibhopcheat_discord_threadid", "0", "If thread_id is provided, the message will send in that thread.", FCVAR_PROTECTED); | ||
AutoExecConfig(true); | ||
|
||
GetPluginInfo(INVALID_HANDLE, PlInfo_Name, g_sPluginName, sizeof(g_sPluginName)); | ||
} | ||
|
||
public void OnAllPluginsLoaded() | ||
{ | ||
g_Plugin_SourceBans = LibraryExists("sourcebans++"); | ||
g_Plugin_ExtDiscord = LibraryExists("ExtendedDiscord"); | ||
} | ||
|
||
public void OnLibraryAdded(const char[] sName) | ||
{ | ||
if (strcmp(sName, "sourcebans++", false) == 0) | ||
g_Plugin_SourceBans = true; | ||
if (strcmp(sName, "ExtendedDiscord", false) == 0) | ||
g_Plugin_ExtDiscord = true; | ||
} | ||
|
||
public void OnLibraryRemoved(const char[] sName) | ||
{ | ||
if (strcmp(sName, "sourcebans++", false) == 0) | ||
g_Plugin_SourceBans = false; | ||
if (strcmp(sName, "ExtendedDiscord", false) == 0) | ||
g_Plugin_ExtDiscord = false; | ||
} | ||
|
||
public void OnMapInit(const char[] mapName) | ||
{ | ||
FormatEx(g_sMap, sizeof(g_sMap), mapName); | ||
} | ||
|
||
public void AntiBhopCheat_OnClientDetected(int client, char[] sReason, char[] sStats) | ||
{ | ||
char sWebhookURL[WEBHOOK_URL_MAX_SIZE]; | ||
g_cvWebhook.GetString(sWebhookURL, sizeof sWebhookURL); | ||
if (!sWebhookURL[0]) { | ||
LogError("[%s] No webhook found or specified.", g_sPluginName); | ||
return; | ||
} | ||
|
||
char sAuth[32]; | ||
GetClientAuthId(client, AuthId_Steam2, sAuth, sizeof(sAuth), false); | ||
|
||
char sPlayer[256]; | ||
if (g_Plugin_SourceBans) { | ||
int iClientBans = 0; | ||
int iClientComms = 0; | ||
|
||
#if defined _sourcebanschecker_included | ||
iClientBans = SBPP_CheckerGetClientsBans(client); | ||
iClientComms = SBPP_CheckerGetClientsComms(client); | ||
#endif | ||
|
||
FormatEx(sPlayer, sizeof(sPlayer), "%N (%d bans - %d comms) [%s] %s.", client, iClientBans, iClientComms, sAuth, sReason); | ||
} else { | ||
FormatEx(sPlayer, sizeof(sPlayer), "%N [%s] %s.", client, sAuth, sReason); | ||
} | ||
|
||
char sTime[64]; | ||
int iTime = GetTime(); | ||
FormatTime(sTime, sizeof(sTime), "Date : %d/%m/%Y @ %H:%M:%S", iTime); | ||
|
||
char sCount[32]; | ||
int iMaxPlayers = MaxClients; | ||
int iConnected = GetPlayerCount(g_cvCountBots.BoolValue); | ||
FormatEx(sCount, sizeof(sCount), "Players : %d/%d", iConnected, iMaxPlayers); | ||
|
||
char sHeader[512], sMessage[WEBHOOK_MSG_MAX_SIZE]; | ||
FormatEx(sHeader, sizeof(sHeader), "%s \nCurrent map : %s \n%s \n%s", sPlayer, g_sMap, sTime, sCount); | ||
|
||
// Discord character limit is 2000 (discord msg + stats) | ||
if (strlen(sHeader) + strlen(sStats) < WEBHOOK_MSG_MAX_SIZE) | ||
{ | ||
FormatEx(sMessage, sizeof(sMessage), "```%s \n\n%s```", sHeader, sStats); | ||
ReplaceString(sMessage, sizeof(sMessage), "\\n", "\n"); | ||
SendWebHook(sMessage, sWebhookURL); | ||
} | ||
else | ||
{ | ||
// First part: Header infos | ||
FormatEx(sMessage, sizeof(sMessage), "```%s```", sHeader); | ||
ReplaceString(sMessage, sizeof(sMessage), "\\n", "\n"); | ||
SendWebHook(sMessage, sWebhookURL); | ||
|
||
// Second part: Stats | ||
FormatEx(sMessage, sizeof(sMessage), "```%s```", sStats); | ||
ReplaceString(sMessage, sizeof(sMessage), "\\n", "\n"); | ||
SendWebHook(sMessage, sWebhookURL); | ||
} | ||
} | ||
|
||
stock void SendWebHook(char sMessage[WEBHOOK_MSG_MAX_SIZE], char sWebhookURL[WEBHOOK_URL_MAX_SIZE]) | ||
{ | ||
Webhook webhook = new Webhook(sMessage); | ||
|
||
char sThreadID[32], sThreadName[WEBHOOK_THREAD_NAME_MAX_SIZE]; | ||
g_cvThreadID.GetString(sThreadID, sizeof sThreadID); | ||
g_cvThreadName.GetString(sThreadName, sizeof sThreadName); | ||
|
||
bool IsThread = g_cvChannelType.BoolValue; | ||
|
||
if (IsThread) { | ||
if (!sThreadName[0] && !sThreadID[0]) { | ||
LogError("[%s] Thread Name or ThreadID not found or specified.", g_sPluginName); | ||
delete webhook; | ||
return; | ||
} else { | ||
if (strlen(sThreadName) > 0) { | ||
webhook.SetThreadName(sThreadName); | ||
sThreadID[0] = '\0'; | ||
} | ||
} | ||
} | ||
|
||
char sAvatar[256]; | ||
g_cvAvatar.GetString(sAvatar, sizeof(sAvatar)); | ||
|
||
if (strlen(sAvatar) > 0) | ||
webhook.SetAvatarURL(sAvatar); | ||
|
||
DataPack pack = new DataPack(); | ||
if (IsThread && strlen(sThreadName) <= 0 && strlen(sThreadID) > 0) | ||
pack.WriteCell(1); | ||
else | ||
pack.WriteCell(0); | ||
pack.WriteString(sMessage); | ||
pack.WriteString(sWebhookURL); | ||
|
||
webhook.Execute(sWebhookURL, OnWebHookExecuted, pack, sThreadID); | ||
delete webhook; | ||
} | ||
|
||
public void OnWebHookExecuted(HTTPResponse response, DataPack pack) | ||
{ | ||
static int retries = 0; | ||
pack.Reset(); | ||
|
||
bool IsThreadReply = pack.ReadCell(); | ||
|
||
char sMessage[WEBHOOK_MSG_MAX_SIZE], sWebhookURL[WEBHOOK_URL_MAX_SIZE]; | ||
pack.ReadString(sMessage, sizeof(sMessage)); | ||
pack.ReadString(sWebhookURL, sizeof(sWebhookURL)); | ||
|
||
delete pack; | ||
|
||
if ((!IsThreadReply && response.Status != HTTPStatus_OK) || (IsThreadReply && response.Status != HTTPStatus_NoContent)) { | ||
if (retries < g_cvWebhookRetry.IntValue) { | ||
PrintToServer("[%s] Failed to send the webhook. Resending it .. (%d/%d)", g_sPluginName, retries, g_cvWebhookRetry.IntValue); | ||
SendWebHook(sMessage, sWebhookURL); | ||
retries++; | ||
return; | ||
} | ||
} else { | ||
if (!g_Plugin_ExtDiscord) { | ||
LogError("[%s] Failed to send the webhook after %d retries, aborting.", g_sPluginName, retries); | ||
LogError("[%s] Failed message : %s", g_sPluginName, sMessage); | ||
} | ||
#if defined _extendeddiscord_included | ||
else { | ||
ExtendedDiscord_LogError("[%s] Failed to send the webhook after %d retries, aborting.", g_sPluginName, retries); | ||
ExtendedDiscord_LogError("[%s] Failed message : %s", g_sPluginName, sMessage); | ||
} | ||
#endif | ||
} | ||
|
||
retries = 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
project: | ||
sourceknight: 0.2 | ||
name: AntiBhopCheat_Discord | ||
dependencies: | ||
- name: sourcemod | ||
type: tar | ||
version: 1.11.0-git6934 | ||
location: https://sm.alliedmods.net/smdrop/1.11/sourcemod-1.11.0-git6934-linux.tar.gz | ||
unpack: | ||
- source: /addons | ||
dest: /addons | ||
|
||
- name: utilshelper | ||
type: git | ||
repo: https://github.com/srcdslab/sm-plugin-UtilsHelper | ||
unpack: | ||
- source: /addons/sourcemod/scripting/include | ||
dest: /addons/sourcemod/scripting/include | ||
|
||
- name: discordwebapi | ||
type: git | ||
repo: https://github.com/srcdslab/sm-plugin-DiscordWebhookAPI | ||
unpack: | ||
- source: /include | ||
dest: /addons/sourcemod/scripting/include | ||
|
||
- name: sourcebans-pp | ||
type: git | ||
repo: https://github.com/srcdslab/sourcebans-pp | ||
unpack: | ||
- source: /game/addons | ||
dest: /addons | ||
|
||
- name: Extended-Discord | ||
type: git | ||
repo: https://github.com/srcdslab/sm-plugin-Extended-Discord | ||
unpack: | ||
- source: /addons/sourcemod/scripting/include | ||
dest: /addons/sourcemod/scripting/include | ||
|
||
- name: selectivebhop | ||
type: git | ||
repo: https://github.com/srcdslab/sm-plugin-SelectiveBhop | ||
unpack: | ||
- source: /addons/sourcemod/scripting/include | ||
dest: /addons/sourcemod/scripting/include | ||
|
||
root: / | ||
output: /addons/sourcemod/plugins | ||
targets: | ||
- AntiBhopCheat_Discord |