Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
28 changes: 28 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: CI

on:
push:
branches: [main]
pull_request:

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.14"
cache: pip
- name: Install dependencies
run: python -m pip install -r requirements.txt -r requirements-dev.txt
- name: Lint
run: ruff check .
- name: Test
run: python -m pytest
13 changes: 7 additions & 6 deletions cogs/link_fix.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@
"""

import re
import asyncio
from typing import List
import discord_markdown_ast_parser as dmap
from discord_markdown_ast_parser.parser import NodeType
import logging

from database.models.Member import *
from database.models.Member import Member
from database.models.Role import Role
from database.models.TextChannel import *
from database.models.Guild import *
from database.models.Event import *
from src.websites import *
from src.utils import *
from database.models.TextChannel import GuildMessageableChannel, TextChannel
from database.models.Guild import Guild, OriginalMessage
from database.models.Event import Event
from src.websites import WebsiteLink, websites
from src.utils import Typing, entrypoint_context, group_items, safe_send_coro

import discore

Expand Down
4 changes: 3 additions & 1 deletion cogs/setup.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import asyncio
import json
import logging
import aiohttp

from src import utils
from database.models.Event import *
from database.models.Event import Event

import discore

Expand Down
3 changes: 3 additions & 0 deletions database/models/Event.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@

import discore


__all__ = ('Event',)

class Event(Model):
"""Event Model"""

Expand Down
11 changes: 11 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "-ra"
pythonpath = ["."]

[tool.ruff]
target-version = "py314"
line-length = 120

[tool.ruff.lint]
select = ["E9", "F63", "F7", "F82"]
2 changes: 2 additions & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pytest ~= 8.4
ruff ~= 0.12
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
discore @ git+https://github.com/Kyrela/discore
discore @ git+https://github.com/Kyrela/discore@d266d4683563b1cd03cf3b6e3149bc11b98dd358
python-i18n ~= 0.3.9
psutil ~= 7.2.2
masonite-orm @ git+https://github.com/MasoniteFramework/orm@c4959b4cadfc5207e48ae0f3918d0c1214e25865 # Temporary fix for Masonite ORM until next, hopefully stable, release
pymysql ~= 1.1.1
discord_markdown_ast_parser @ git+https://github.com/Kyrela/discord-markdown-ast-parser
discord_markdown_ast_parser @ git+https://github.com/Kyrela/discord-markdown-ast-parser@9e38d0415a900914edcbe492cbe39323e273d596
aiohttp ~= 3.13.3
7 changes: 4 additions & 3 deletions src/websites.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
"""
Allows fixing links from various websites.
"""
import asyncio
import logging
import re
from typing import Type, Iterable, Callable
from typing import Type, Iterable, Callable, Self

from database.models.Event import *
from database.models.Guild import *
from database.models.Event import Event
from database.models.Guild import EmbedEzView, FxEmbedView, Guild, InstagramView, TiktokView
from src import utils

__all__ = ('WebsiteLink', 'websites')
Expand Down
6 changes: 6 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import discore


def pytest_configure():
if not discore.config.loaded:
discore.config_init()
46 changes: 46 additions & 0 deletions tests/test_link_parsing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import asyncio

import discord_markdown_ast_parser as dmap

from cogs.link_fix import get_embeddable_urls
from database.models.Guild import FxEmbedView
from src.websites import TwitterLink, generate_regex


class FakeGuild:
lang = 'en'

def __init__(self, **settings):
self.settings = settings

def __getitem__(self, key):
return self.settings[key]


def test_markdown_parser_ignores_code_and_preserves_spoilers():
nodes = dmap.parse('`https://x.com/ignored/status/1` ||https://x.com/user/status/2||')

assert get_embeddable_urls(nodes) == [('https://x.com/user/status/2', True)]


def test_generated_route_requires_the_whole_url_to_match():
regex = generate_regex('example.com', '/:username/post/:id')

match = regex.fullmatch('https://www.example.com/alice/post/42?ref=test')
assert match is not None
assert match['username'] == 'alice'
assert match['id'] == '42'
assert regex.fullmatch('https://evil.example/example.com/alice/post/42') is None


def test_twitter_link_renders_expected_proxy():
guild = FakeGuild(
twitter=True,
twitter_view=FxEmbedView.NORMAL,
twitter_tr=False,
)
link = TwitterLink(guild, 'https://x.com/alice/status/42')

fixed_url, label = asyncio.run(link.get_fixed_url())
assert fixed_url == 'https://fxtwitter.com/i/status/42'
assert label == 'FxTwitter'
12 changes: 12 additions & 0 deletions tests/test_project_files.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from pathlib import Path

import yaml


ROOT = Path(__file__).parents[1]


def test_all_locale_files_are_valid_yaml():
for locale_file in (ROOT / 'locales').glob('*.yml'):
with locale_file.open(encoding='utf-8') as stream:
assert isinstance(yaml.safe_load(stream), dict), locale_file
8 changes: 8 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from src.utils import group_items


def test_group_items_never_exceeds_limit_when_items_fit():
groups = group_items(['abc', 'de', 'fgh'], max_group_size=6, sep='|')

assert groups == [('abc|de', ['abc', 'de']), ('fgh', ['fgh'])]
assert all(len(text) <= 6 for text, _ in groups)
Loading