Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.22.11 - mediaonly forums, fixes, CI improvements #145

Merged
merged 34 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
05cfda3
ci: try to actually get tags lol
Borketh Sep 25, 2024
0138bb7
fix: poetry needs to know about fred sooner to give him a version (2.…
Borketh Sep 26, 2024
9be909a
fix: set error_channel responds with channel mention now
Borketh Sep 26, 2024
1a94289
build: update postgres and pgadmin
Borketh Sep 26, 2024
0b6e7c7
fix: random unicode entry in the initial crash example db
Borketh Sep 26, 2024
3c3093e
ci: deduplicate compose spec
Borketh Sep 30, 2024
b9216cc
ci: fixup and streamline apk poetry
Borketh Sep 30, 2024
60d6a45
fix: make poetry run fred valid again
Borketh Oct 6, 2024
eee7cff
fix: properly parse FG log
Borketh Oct 6, 2024
f15e102
build: fix transient build issue with alpine
Borketh Oct 6, 2024
8207c20
fix: handle edge case where trigger message is deleted before reply
Borketh Oct 6, 2024
15b2f1d
chore: update poetry.lock
Borketh Oct 6, 2024
b955428
chore: version bump (2.22.11)
Borketh Oct 6, 2024
3193c71
fix: remove delay accidentally left in reply_to_msg
Borketh Oct 8, 2024
d41fd4d
fix: BadArgument was expected to have some format we were string parsing
Borketh Oct 9, 2024
6fdc2a7
fix: move set error_channel and fix it not actually setting error_cha…
Borketh Oct 9, 2024
3394556
feat: mediaonly forum channels
Borketh Oct 9, 2024
a4cc938
log: log deleting bot's own message on x react
Borketh Oct 9, 2024
0aabbf7
chore: update poetry.lock
Borketh Oct 9, 2024
502a2f3
remove(dialogflow): remove df dependency and comment out references
Borketh Oct 10, 2024
2922f0b
chore(logging): better error messages and not flooding the log with q…
Borketh Oct 10, 2024
f5fee2d
fix(crashes): remove extraneous backticks from path readout
Borketh Oct 10, 2024
ebcfb65
fix(crashes): use crash name instead of linked command name
Borketh Oct 10, 2024
75479a7
remove(dialogflow): remove all code references to df
Borketh Oct 10, 2024
226ce50
remove(dialogflow): drop tables related to df
Borketh Oct 10, 2024
208cafa
remove(dialogflow): leftovers
Borketh Oct 10, 2024
ca002aa
chore(mediaonly): simplify processing function
Borketh Oct 11, 2024
f71cffa
fix: log *who* reacted x to delete a fred message
Borketh Oct 11, 2024
b58b0e4
chore: update poetry.lock
Borketh Oct 11, 2024
e85c893
Merge branch 'bork-fixes' into no-dialogflow
Borketh Oct 11, 2024
a28177f
remove(dialogflow): remove df from exampledb.sql
Borketh Oct 11, 2024
e8ac29d
fix(dialogflow): fix experience.py
Borketh Oct 11, 2024
2e765de
chore(dialogflow): final poetry.lock for no-df
Borketh Oct 11, 2024
17cf3a6
Merge pull request #147 from satisfactorymodding/no-dialogflow
Borketh Oct 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,18 @@ jobs:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}


- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=ref,event=pr
type=sha


- uses: docker/setup-buildx-action@v3
Expand Down
4 changes: 2 additions & 2 deletions docker-compose-deps.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
postgres:
image: postgres:14.0-alpine
image: postgres:14-alpine
environment:
POSTGRES_PASSWORD: fred
POSTGRES_USER: fred
Expand All @@ -14,7 +14,7 @@ services:
pgadmin:
depends_on:
- postgres
image: dpage/pgadmin4:6
image: dpage/pgadmin4:8
environment:
PGADMIN_DEFAULT_EMAIL: '[email protected]'
PGADMIN_DEFAULT_PASSWORD: 'fred'
Expand Down
27 changes: 3 additions & 24 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
include:
- docker-compose-deps.yml
services:
fred:
depends_on:
Expand All @@ -16,27 +18,4 @@ services:
FRED_SQL_HOST: postgres
FRED_SQL_PORT: 5432
ports:
- "80:80"

postgres:
image: postgres:14.0-alpine
environment:
POSTGRES_PASSWORD: fred
POSTGRES_USER: fred
PGDATA: /var/lib/postgresql/data/pgdata
volumes:
- pgdata:/var/lib/postgresql/data/pgdata:z
- ./docker/exampledb.sql:/docker-entrypoint-initdb.d/exampledb.sql

pgadmin:
depends_on:
- postgres
image: dpage/pgadmin4:6
environment:
PGADMIN_DEFAULT_EMAIL: '[email protected]'
PGADMIN_DEFAULT_PASSWORD: 'fred'
ports:
- "8080:80"

volumes:
pgdata:
- "80:80"
27 changes: 15 additions & 12 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,32 +1,35 @@
FROM python:3.12-alpine AS runtime
FROM alpine AS runtime
#FROM python:3.12-slim AS runtime

VOLUME /config
WORKDIR /app

RUN apk update; apk add --no-cache tesseract-ocr-data-eng re2-dev
RUN apk update; apk add --no-cache python3 tesseract-ocr-data-eng re2-dev
#ENV DEBIAN_FRONTEND=noninteractive APT="apt-get -qq"
#RUN $APT update; \
# $APT install tesseract-ocr; \
# $APT clean; \
# rm -rf /var/lib/apt/lists/*

FROM python:3.12-alpine AS build
FROM alpine AS build
#FROM python:3.12-slim AS build

WORKDIR /deps

RUN pip --no-cache-dir install --progress-bar=off "poetry==1.8"
RUN apk update; apk add g++ git re2-dev
COPY pyproject.toml .
COPY poetry.lock .
RUN poetry install -nvvv --only main --no-root
RUN mv $(poetry env info --path) ./venv
#RUN pip --no-cache-dir install --progress-bar=off "poetry==1.8"
RUN apk update
RUN apk add --no-cache g++ git re2-dev poetry python3-dev
COPY pyproject.toml poetry.lock poetry.toml ./
RUN python -VV
RUN poetry env use $(which python)
RUN poetry install -nvvv --no-root --compile --only main
COPY fred ./fred/
RUN poetry install -nvvv --only-root --compile

FROM runtime

COPY --from=build /deps/venv ./venv
COPY --from=build /deps/.venv ./venv
COPY fred ./fred/
COPY *.env .

CMD ./venv/bin/python3 -m fred
RUN pwd
CMD ./venv/bin/python -m fred

Check warning on line 35 in docker/Dockerfile

View workflow job for this annotation

GitHub Actions / build-and-push

JSON arguments recommended for ENTRYPOINT/CMD to prevent unintended behavior related to OS signals

JSONArgsRecommended: JSON arguments recommended for CMD to prevent unintended behavior related to OS signals More info: https://docs.docker.com/go/dockerfile/rule/json-args-recommended/
2 changes: 1 addition & 1 deletion docker/exampledb.sql
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,7 @@ COPY public.crashes (id, name, crash, response) FROM stdin;
54 .netmissing Install a version of .NET Framework SDK at Your .NET Framework install is either missing or oudated. Please download and install the latest one from https://dotnet.microsoft.com/download/visual-studio-sdks. Make sure to download the .NET **Framework**SDK
55 noautomationtool UATHelper: Package Mod Task (Windows): RunUAT.bat ERROR: Visual studio and/or AutomationTool.csproj was not found, nor was Engine\\Binaries\\DotNET\\AutomationTool.exe. Can't run the automation tool. Open your .sln with Visual Studio/Rider and build the project for Shipping
64 tolowercase c\\.toLowerCase is not a function >tolowercase
68 flip \\(╯°□°\\╯︵ ┻━┻ ┬─┬ ノ( ゜-゜ノ)
68 flip \\(╯°□°\\)╯︵ ┻━┻ ┬─┬ ノ( ゜-゜ノ)
69 fixit Can we (fix\\s*it|ficsit)\\s*? Yes we can!
70 oldproject ERROR: Cannot find game version file Your project is outdated. Please update it
71 needcompile Module\\s+[‘‘'’`]*FactoryGame[‘‘'’`]*\\s+could\\s+not\\s+be\\s+found Please open your .sln with Visual Studio/Rider and build the project for both Development Editor and Shipping
Expand Down
8 changes: 6 additions & 2 deletions fred/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@
from .fred import Bot, nextcord


async def main(): # this is so poetry can run a function from here properly
async def a_main():
intents = nextcord.Intents.all()

client = Bot("?", help_command=None, intents=intents, chunk_guilds_at_startup=False)
await client.start(getenv("FRED_TOKEN"), reconnect=True)


def main(): # this is so poetry can run a function from here properly
asyncio.run(a_main())


if __name__ == "__main__":
asyncio.run(main())
main()
46 changes: 36 additions & 10 deletions fred/cogs/crashes.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ async def mass_regex(self, text: str) -> AsyncIterator[CrashResponse]:
if command_response.startswith(self.bot.command_prefix): # is alias
command = config.Commands.fetch(command_response.strip(self.bot.command_prefix))
yield CrashResponse(
name=command["name"],
name=crash["name"],
value=command["content"],
attachment=command["attachment"],
inline=True,
Expand Down Expand Up @@ -472,6 +472,29 @@ def from_metadata_json(cls: Type[InstallInfo], file: IO[bytes], filename: str) -
game_command_line=selected_installation.get("launchPath", ""),
installed_mods=installed_mods,
)

case {
# SMM 2 format - keys missing when generated when no installs found
"installsFound": _installations,
"selectedInstall": selected_installation,
"profiles": _profiles,
"selectedProfile": _selected_profile,
"smmVersion": smm_version,
"modsEnabled": _mods_enabled,
}:
# if there is no install everything can default to None
selected_installation = selected_installation or {}
return cls(
filename,
smm_version=smm_version,
sml_version="",
game_version=selected_installation.get("version", ""),
game_type="WindowsClient", # SMM 2 only supports this one and therefore doesn't specify otherwise
game_path=selected_installation.get("installLocation", ""),
game_command_line=selected_installation.get("launchPath", ""),
installed_mods={},
)

case _:
logger.exception(ValueError("Invalid SMM metadata json"))
return None
Expand Down Expand Up @@ -500,7 +523,7 @@ def update_from_fg_log(self, log_file: IO[bytes]):
p1 = p1.lower()
p2 = p2.lower()
if Path(p1) != Path(p2):
self.mismatches.append(f"Game Path: (`{path}`)")
self.mismatches.append(f"Game Path: ({path})")
else:
self.game_path = path

Expand All @@ -516,15 +539,17 @@ def update_from_fg_log(self, log_file: IO[bytes]):

@staticmethod
def _get_fg_log_details(log_file: IO[bytes]):
lines = log_file.readlines()
# This function uses lazy evaluation to get the info we need without performing regex on the whole log
# It used to matter more when we were using slower regex libraries. - Borketh

vanilla_info_search_area = filter(lambda l: re2.match("^LogInit", str(l)), lines)
lines: list[bytes] = log_file.readlines()
vanilla_info_search_area = filter(lambda l: re2.match("^LogInit", l), map(bytes.decode, lines))

info = {}
patterns = [
re2.compile(r"Net CL: (?P<game_version>\d+)"),
re2.compile(r"Command Line: (?P<cli>.*)"),
re2.compile(r"Base Directory: (?P<path>.+)"),
re2.compile(r"Command Line:(?P<cli>.*)"),
re2.compile(r"Base Directory:(?P<path>.+)"),
re2.compile(r"Launcher ID: (?P<launcher>\w+)"),
]

Expand All @@ -540,9 +565,10 @@ def _get_fg_log_details(log_file: IO[bytes]):
info |= match.groupdict()
patterns.pop(0)
else:
logger.info("Didn't find all four pieces of information normally found in a log")
logger.info("Didn't find all four pieces of information normally found in a log!")
logger.debug(json.dumps(info, indent=2))

mod_loader_logs = filter(lambda l: re2.match("LogSatisfactoryModLoader", str(l)), lines)
mod_loader_logs = filter(lambda l: re2.match("LogSatisfactoryModLoader", l), map(bytes.decode, lines))
for line in mod_loader_logs:
if match := re2.search(r"(?<=v\.)(?P<sml>[\d.]+)", line):
info |= match.groupdict()
Expand All @@ -557,7 +583,7 @@ def _get_fg_log_details(log_file: IO[bytes]):
return info

def _version_info(self) -> str:
# note: (str that defaults to "") and (f-string) is shorthand for if str: f-string
# note: `(str that defaults to "") and (f-string)` is shorthand for if str: f-string
version_info = (
"```\n"
+ (self.smm_version and f"SMM Version: {self.smm_version}\n")
Expand All @@ -574,7 +600,7 @@ def _version_info(self) -> str:
+ self.game_type
+ f" CL {self.game_version}"
+ (self.game_launcher_id and f" from {self.game_launcher_id}")
+ (self.game_path and f"\nPath: `{self.game_path}`")
+ (self.game_path and f"\nPath: `{self.game_path.strip()}`")
+ "\n"
)

Expand Down
69 changes: 54 additions & 15 deletions fred/cogs/mediaonly.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from nextcord import Message
from nextcord import Message, Thread, ForumChannel

from .. import config
from ..libraries import common
Expand All @@ -9,7 +9,22 @@ class MediaOnly(FredCog):

async def process_message(self, message: Message) -> bool:
"""Returns whether the message was removed."""
self.logger.info("Processing a message", extra=common.message_info(message))
if isinstance(message.channel, Thread):
if (
isinstance(message.channel.parent, ForumChannel)
and message.id == message.channel.id # we only care if it's the initial post
and config.MediaOnlyChannels.check(message.channel.parent_id) # last because it's a DB call
):
return await self._process_forum_message(message)
else:
return False
elif config.MediaOnlyChannels.check(message.channel.id):
return await self._process_regular_message(message)

return False

async def _process_regular_message(self, message: Message) -> bool:
self.logger.info("Checking a message", extra=common.message_info(message))

if len(message.embeds) > 0 or len(message.attachments) > 0:
self.logger.info("Message contains media", extra=common.message_info(message))
Expand All @@ -21,17 +36,41 @@ async def process_message(self, message: Message) -> bool:
self.logger.info("Message doesn't contain media but the author is a T3", extra=common.message_info(message))
return False

if config.MediaOnlyChannels.check(message.channel.id):
self.logger.info("Removing a message", extra=common.message_info(message))
await message.delete()
await self.bot.send_DM(
message.author,
f"Hi {message.author.name}, the channel you just tried to message in, "
f"{self.bot.get_channel(message.channel.id).name} is a 'Media Only' channel. "
f"This means you must attach a file in order to post there. "
f"Here is your message if you want to paste it again after the adequate changes: "
f"```\n{message.content}\n```",
)
return True
self.logger.info("Removing a message", extra=common.message_info(message))
await message.delete()
await self.bot.send_DM(
message.author,
f"Hi {message.author.mention}, "
f"{message.channel.mention} is a 'media-only' channel. "
f"This means posts there must have files or embedded links. "
f"Here is your message if you want to paste it again after the adequate changes: "
f"```\n{message.content}\n```",
)
return True

return False
async def _process_forum_message(self, message: Message) -> bool:

self.logger.info("Checking a thread", extra=common.message_info(message))

if len(message.embeds) > 0 or len(message.attachments) > 0:
self.logger.info("Message contains media", extra=common.message_info(message))
return False

ctx = await self.bot.get_context(message)

if await common.l4_only(ctx):
self.logger.info("Message doesn't contain media but the author is a T3", extra=common.message_info(message))
return False

self.logger.info("Removing a thread", extra=common.message_info(message))
await message.channel.delete()
await self.bot.send_DM(
message.author,
f"Hi {message.author.mention}, "
f"{message.channel.parent.mention} is a 'media-only' forum. "
f"This means posts there must have files or embedded links. "
f"Here is your message if you want to paste it again after the adequate changes: "
f"\n\n**Title: **`{message.channel.name}`\n"
f"```\n{message.content}\n```",
)
return True
6 changes: 5 additions & 1 deletion fred/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import nextcord
from sqlobject import SQLObject, IntCol, BoolCol, JSONCol, BigIntCol, StringCol, FloatCol, sqlhub
from sqlobject.dberrors import DuplicateEntryError


class PermissionRoles(SQLObject):
Expand Down Expand Up @@ -282,7 +283,10 @@ def migrate():
for migration in valid_migrations:
sqlhub.processConnection.query(migration.read_text())

Misc.create_or_change("migration_rev", _migration_rev(migrations_filenames[0]))
try:
Misc.create_or_change("migration_rev", _migration_rev(migrations_filenames[0]))
except DuplicateEntryError as e:
print(f"UNABLE TO RUN MIGRATION DUE TO {e}")


def _migration_rev(filepath: pathlib.Path) -> int:
Expand Down
Loading