maint: push updates from other repo

This commit is contained in:
2024-08-29 20:06:39 +02:00
parent d88951a473
commit 98677a1ca6
6 changed files with 245 additions and 17 deletions

View File

@@ -14,13 +14,13 @@ jobs:
if: github.ref_type == 'tag'
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@main
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.4.0
uses: docker/setup-buildx-action@v3.6.1
- name: Log in to DockerHub
uses: docker/login-action@v3.2.0
uses: docker/login-action@v3.3.0
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
@@ -36,10 +36,10 @@ jobs:
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v6.3.0
uses: docker/build-push-action@v6.7.0
with:
context: .
platforms: linux/amd64
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

View File

@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@main
- name: Install pip
run: |
@@ -26,6 +26,7 @@ jobs:
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install flake8
- name: Run flake8
run: |

View File

@@ -1,2 +1,7 @@
# AlterWare's Discord Bot
This repo contains the AlterWare Bot's source code. It is written in Python using discord.py
This repo contains the AlterWare Bot written in python using discord.py
Contributions are welcome! Please follow the guidelines below:
- Sign [AlterWare CLA](https://alterware.dev/cla) and send a pull request or email your patch at patches@alterware.dev
- Make sure that PRs have only one commit, and deal with one issue only

197
aw.py
View File

@@ -1,7 +1,8 @@
import datetime
import json
import os
import random
import re
from datetime import datetime, timedelta, timezone
from typing import Literal
import discord
@@ -22,6 +23,7 @@ ALLOWED_CHANNELS = [
1145459788151537804,
1145469106133401682,
1117540484085194833,
1112049391482703873,
]
GENERAL_CHANNEL = 1110531063744303138
@@ -36,6 +38,10 @@ bot = commands.Bot(command_prefix="!", intents=discord.Intents.all())
tree = bot.tree
def aware_utcnow():
return datetime.now(timezone.utc)
def fetch_api_data():
response = requests.get("https://api.getserve.rs/v1/servers/alterware")
if response.status_code == 200:
@@ -146,8 +152,84 @@ async def on_tree_error(
bot.tree.on_error = on_tree_error
async def detect_ghost_ping(message):
if not message.mentions:
return
channel = bot.get_channel(BOT_LOG)
if channel:
embed = discord.Embed(
title="Ghost Ping",
description="A ghost ping was detected.",
color=0xDD2E44,
)
embed.add_field(
name="Author", value=message.author.mention, inline=True
) # noqa
embed.add_field(
name="Channel", value=message.channel.mention, inline=True
) # noqa
mentioned_users = ", ".join([user.name for user in message.mentions])
embed.add_field(
name="Mentions",
value=f"The message deleted by {message.author} mentioned: {mentioned_users}", # noqa
inline=False,
) # noqa
embed.set_footer(
text=f"Message ID: {message.id} | Author ID: {message.author.id}"
)
await channel.send(embed=embed)
async def detect_ghost_ping_in_edit(before, after):
before_mentions = set(before.mentions)
after_mentions = set(after.mentions)
if before_mentions == after_mentions:
return
added_mentions = after_mentions - before_mentions
removed_mentions = before_mentions - after_mentions
response = "The mentions in the message have been edited.\n"
if added_mentions:
response += f"Added mentions: {', '.join(user.name for user in added_mentions)}\n" # noqa
if removed_mentions:
response += f"Removed mentions: {', '.join(user.name for user in removed_mentions)}" # noqa
channel = bot.get_channel(BOT_LOG)
if channel:
embed = discord.Embed(
title="Ghost Ping",
description="A ghost ping was detected.",
color=0xDD2E44,
)
embed.add_field(name="Author", value=before.author.mention, inline=True) # noqa
embed.add_field(
name="Channel", value=before.channel.mention, inline=True
) # noqa
embed.add_field(
name="Mentions",
value=response,
inline=False,
) # noqa
embed.set_footer(
text=f"Message ID: {before.id} | Author ID: {before.author.id}"
)
await channel.send(embed=embed)
@bot.event
async def on_message_delete(message):
if message.author == bot.user:
return
channel = bot.get_channel(BOT_LOG)
if channel:
embed = discord.Embed(
@@ -163,10 +245,23 @@ async def on_message_delete(message):
) # noqa
if message.content:
embed.add_field(name="Content", value=message.content, inline=False) # noqa
if message.reference is not None:
original_message = await message.channel.fetch_message(
message.reference.message_id
)
embed.add_field(
name="Replied",
value=original_message.author.mention,
inline=False, # noqa
) # noqa
embed.set_footer(
text=f"Message ID: {message.id} | Author ID: {message.author.id}"
)
await detect_ghost_ping(message)
await channel.send(embed=embed)
@@ -191,12 +286,40 @@ async def on_bulk_message_delete(messages):
name="Content", value=message.content, inline=False
) # noqa
embed.set_footer(
text=f"Message ID: {message.id} | Author ID: {message.author.id}" # noqa
text=f"Message ID: {message.id} | Author ID: {message.author.id}" # noqa
)
await channel.send(embed=embed)
@bot.event
async def on_message_edit(before, after):
channel = bot.get_channel(BOT_LOG)
if channel:
if not before.content:
return
if after.content and after.content == before.content:
return
embed = discord.Embed(
title="Edited Message",
description="A message was edited.",
color=0xDD2E44,
)
embed.add_field(name="Author", value=before.author.mention, inline=True) # noqa
embed.add_field(
name="Channel", value=before.channel.mention, inline=True
) # noqa
embed.add_field(name="Content", value=before.content, inline=False) # noqa
embed.set_footer(
text=f"Message ID: {before.id} | Author ID: {before.author.id}"
)
await detect_ghost_ping_in_edit(before, after)
await channel.send(embed=embed)
@bot.event
async def on_message(message):
if message.author == bot.user:
@@ -204,13 +327,13 @@ async def on_message(message):
# Too many mentions
if len(message.mentions) >= 3:
await message.delete()
member = message.guild.get_member(message.author.id)
if member:
# Timeout the member for 60 seconds
# Timeout the member
await member.timeout_for(
discord.utils.utcnow() + datetime.timedelta(seconds=60)
discord.utils.utcnow() + datetime.timedelta(minutes=5)
)
await message.delete()
return
# Auto delete torrent if post in chat.
@@ -226,14 +349,70 @@ async def on_message(message):
# print('Checking for patterns...')
for pattern in patterns:
if re.search(pattern["regex"], message.content, re.IGNORECASE):
# print('Checking message content:', message.content, re.IGNORECASE) # noqa
# print('Matching pattern regex:', pattern['regex']) # noqa
# print('Pattern match:', re.search(pattern['regex'], message.content, re.IGNORECASE)) # noqa
response = pattern["response"]
await message.channel.send(response)
reply_message = await message.reply(response, mention_author=True)
await reply_message.add_reaction("\U0000274C")
break
@bot.event
async def on_reaction_add(reaction, user):
if reaction.emoji != "\U0000274C":
return
if reaction.message.author != bot.user:
return
current_time = aware_utcnow()
time_difference = current_time - reaction.message.created_at
if time_difference > timedelta(minutes=5):
return
if reaction.message.reference is None:
return
original_message = await reaction.message.channel.fetch_message(
reaction.message.reference.message_id
)
if original_message.author == user:
await reaction.message.delete()
def generate_random_nickname():
random_number = random.randint(1, 99)
return f"Unknown Soldier {random_number:02d}"
def is_valid_username(username):
pattern = r"^[\d\x00-\x7F\xC0-\xFF]{2,}"
return bool(re.match(pattern, username))
@bot.event
async def on_member_join(member):
name_to_check = member.name
if member.display_name:
name_to_check = member.display_name
if len(name_to_check) < 3 or not is_valid_username(name_to_check):
new_nick = generate_random_nickname()
await member.edit(nick=new_nick)
@bot.event
async def on_member_update(before, after):
name_to_check = after.name
if after.nick:
name_to_check = after.nick
if len(name_to_check) < 3 or not is_valid_username(name_to_check):
new_nick = generate_random_nickname()
await after.edit(nick=new_nick)
# Update Player Counts from API
@tasks.loop(minutes=10)
async def update_status():

View File

@@ -3,6 +3,22 @@
"regex": "(?:do\\s+|if\\s+i\\s+don't\\s+)?(?:i|you)?\\s*(?:really\\s+)?(?:need\\s+to|have\\s+to|must|gotta|can)\\s+own\\s+(?:an?\\s+)?(?:official\\s+)?(?:copy\\s+of\\s+)?(?:the\\s+|this\\s+|said\\s+|these\\s+|those\\s+)?(?:cod\\s+)?games?\\s*(?:on\\s+steam|on\\s+alterware)?",
"response": "Yes, it is required to own a copy of the game to utilize our clients"
},
{
"regex": "own(ing)* the game",
"response": "Yes, it is required to own a copy of the game to utilize our clients"
},
{
"regex": "^.*?\\bbuy\\b.*?\\btwice\\b.*?$",
"response": "There is no stipulation in the law that entitles you to a free PC copy of the game if you bought it on another platform"
},
{
"regex": "^.*?\\bbuying\\b.*?\\btwice\\b.*?$",
"response": "There is no stipulation in the law that entitles you to a free PC copy of the game if you bought it on another platform"
},
{
"regex": "^.*?\\bbought\\b.*?\\btwice\\b.*?$",
"response": "There is no stipulation in the law that entitles you to a free PC copy of the game if you bought it on another platform"
},
{
"regex": "\bhow can I open the console ingame\b",
"response": "Press the tilde key (~) or grave key (`) to enter console.\n https://i.imgur.com/drPaC0f.png"
@@ -11,8 +27,36 @@
"regex": "(.*)(HOW|WHERE)(.*)(CHANGE|MODIFY)(.*)(USERNAME|NAME|IGN)(.*)",
"response": "``/name WhateverNameYouWant`` on the in-game console.\nYou open the in-game console with the ~ or ` key (underneath ESC). If you're on a 60% keyboard it's Fn+ESC.\nhttps://i.imgur.com/drPaC0f.png"
},
{
"regex": "^.*?\\bchange\\b.*?\\b(username|name)\\b.*?$",
"response": "``/name WhateverNameYouWant`` on the in-game console.\nYou open the in-game console with the ~ or ` key (underneath ESC). If you're on a 60% keyboard it's Fn+ESC.\nhttps://i.imgur.com/drPaC0f.png"
},
{
"regex": "online profile is invalid",
"response": "Close your game, locate your Modern Warfare 2 game folder, and delete the `players` folder"
},
{
"regex": "vac ban",
"response": "The short answer is no. Our CoD clients are completely external to Steam and Steam servers (you don not play with Steam users). It is impossible to get VAC banned. The servers are completely separate from Steam. You are at no risk of receiving a VAC ban"
},
{
"regex": "do i need Steam",
"response": "Yes, it is required to own a copy of the game on Steam to utilize our clients"
},
{
"regex": "unlock(\\s)*all",
"response": "Just use the 'Unlock All' button in the barracks menu to get 10th prestige level 70 with everything unlocked. On S1 and IW6, you must type `unlockstats` in either the in-game console or the external console"
},
{
"regex": "unlock everything",
"response": "Just use the 'Unlock All' button in the barracks menu to get 10th prestige level 70 with everything unlocked. On S1 and IW6, you must type `unlockstats` in either the in-game console or the external console"
},
{
"regex": "^.*?\\b(get|buy)\\b.*?\\b(dlc|dlcs)\\b.*?$",
"response": "We ask all our users to purchase the DLCs on Steam. If you're looking for instructions on how to get the official IW4x DLC map packs, please refer to this forum post: https://forum.alterware.dev/t/how-to-download-bonus-content-iw4x/901"
},
{
"regex": "steam(\\s)*deck",
"response": "Are you wondering how to install our clients on the Steam Deck? Check out this guide: https://forum.alterware.dev/t/playing-alterware-on-linux-guide-desktop-handheld/1036"
}
]

View File

@@ -1,3 +1,2 @@
discord.py
flake8
requests