Skip to content

Commit

Permalink
Merge d240921 into 1f01e64
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanklee86 committed Jan 17, 2022
2 parents 1f01e64 + d240921 commit 24eae75
Show file tree
Hide file tree
Showing 20 changed files with 236 additions and 46 deletions.
1 change: 1 addition & 0 deletions .env-local
Expand Up @@ -3,6 +3,7 @@ XENFORO_DB_USER = "root"
XENFORO_DB_PASSWORD = "sekretmysqlpw"
XENFORO_DB_NAME = "xenforo"
XENFORO_STOP_REACTION_ID = "10"
XENFORO_BASE_URL = "https://telath.com"

DISCORD_WEBHOOK = "https://abcd.com"

Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Expand Up @@ -32,6 +32,11 @@ jobs:
sleep 10
cp .env-local .env
poetry run pytest
- name: Publish Unit Test Results
uses: EnricoMi/publish-unit-test-result-action@v1
if: always()
with:
files: test_results/results.xml
- name: Send coverage to Coveralls
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
7 changes: 6 additions & 1 deletion Dockerfile
Expand Up @@ -32,4 +32,9 @@ ENV LC_ALL C.UTF-8
ENV LANG =C.UTF-8

# Python variables
ENV PYTHONPATH /source
ENV PYTHONPATH /source

# RUN
# ---------------------------------------------------------------------- #

ENTRYPOINT [ "python", "telathbot/main.py"]
6 changes: 4 additions & 2 deletions Makefile
Expand Up @@ -5,7 +5,9 @@ PROJECT_NAME = telathbot
#-----------------------------------------------------------------------
# Rules of Rules : Grouped rules that _doathing_
#-----------------------------------------------------------------------
test: lint pytest
test: lint local-dev-down local-dev-up pytest

run: local-dev-down local-dev-up run-local

build: clean build-package upload

Expand Down Expand Up @@ -34,7 +36,7 @@ local-dev-down:
# Run Rules
#-----------------------------------------------------------------------

run:
run-local:
uvicorn telathbot:app --reload --host 0.0.0.0

# Run in Docker
Expand Down
10 changes: 5 additions & 5 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion pyproject.toml
Expand Up @@ -7,7 +7,7 @@ license = "MIT"

[tool.poetry.dependencies]
python = "^3.10"
fastapi = "^0.71.0"
fastapi = "^0.72.0"
discord-webhook = "^0.14.0"
uvicorn = "^0.17.0"
prometheus-fastapi-instrumentator = "^5.7.1"
Expand All @@ -16,6 +16,7 @@ aiomysql = "^0.0.22"
mypy = "^0.931"
httpx = "^0.21.3"
umongo = "^3.1.0"
python-dotenv = "^0.19.2"

[tool.poetry.dev-dependencies]
pytest = "^6.2.5"
Expand Down
1 change: 1 addition & 0 deletions telathbot/config.py
Expand Up @@ -19,6 +19,7 @@ class Settings(BaseSettings):
xenforo_db_password: str
xenforo_db_name: str
xenforo_stop_reaction_id: int
xenforo_base_url: str

# Discord
discord_webhook: HttpUrl
Expand Down
4 changes: 4 additions & 0 deletions telathbot/constants.py
@@ -1,5 +1,9 @@
VERSION = "0.1.0"

# Xenforo
XENFORO_THREAD_PAGE_SIZE = 20

# Mongo
TELATHBOT_DB = "telathbot"
METADATA_COLLECTION = "metadata"
SAFETYTOOLS_COLLECTION = "safetytools"
48 changes: 31 additions & 17 deletions telathbot/databases/mysql.py
Expand Up @@ -7,9 +7,7 @@
from telathbot.schemas.reaction import PostReaction


async def get_post_reactions(
start_post_id: int, reaction_id: int
) -> List[PostReaction]:
async def _run_query(query: str):
config = get_settings()

pool = await aiomysql.create_pool(
Expand All @@ -22,25 +20,33 @@ async def get_post_reactions(

async with pool.acquire() as conn:
async with conn.cursor() as cur:
await cur.execute(
f"""
SELECT
post_id,
thread_id,
username,
reactions,
reaction_users
FROM xf_post
WHERE
post_id > {start_post_id} AND
reaction_users like '%reaction_id\":{reaction_id}%';
"""
)
await cur.execute(query)
query_results = await cur.fetchall()

pool.close()
await pool.wait_closed()

return query_results


async def get_post_reactions(
start_post_id: int, reaction_id: int
) -> List[PostReaction]:
query = f"""
SELECT
post_id,
thread_id,
username,
reactions,
reaction_users,
position
FROM xf_post
WHERE
post_id > {start_post_id} AND
reaction_users like '%reaction_id\":{reaction_id}%';
"""
query_results = await _run_query(query)

raw_results = []
for result in query_results:
raw_results.append(
Expand All @@ -50,7 +56,15 @@ async def get_post_reactions(
username=result[2],
reactions=json.loads(result[3]),
reaction_users=json.loads(result[4]),
position=result[5],
)
)

return raw_results


async def get_latest_post_id() -> int:
query = "select max(post_id) from xf_post;"
query_results = await _run_query(query)

return query_results[0][0]
52 changes: 51 additions & 1 deletion telathbot/discord.py
@@ -1,10 +1,16 @@
# pylint: disable=no-member
from discord_webhook import DiscordWebhook
from discord_webhook import DiscordEmbed, DiscordWebhook

from telathbot.config import get_settings
from telathbot.constants import XENFORO_THREAD_PAGE_SIZE
from telathbot.enums import SafetyToolsLevels
from telathbot.logger import LOGGER


def __generate_url(forum_url: str, post_id: int, thread_id: int, position: int) -> str:
return f"{forum_url}/index.php?threads/{thread_id}/page-{(position // XENFORO_THREAD_PAGE_SIZE) + 1}#post-{post_id}"


def send_ip_changed_notification(new_ip: str) -> bool:
config = get_settings()

Expand All @@ -26,3 +32,47 @@ def send_ip_changed_notification(new_ip: str) -> bool:
succeeded = True

return succeeded


def send_safetytools_notification( # pylint: disable=too-many-arguments
level: SafetyToolsLevels,
post_id: int,
thread_id: int,
position: int,
post_user: str,
reaction_users: list[str],
) -> bool:
config = get_settings()

webhook = DiscordWebhook(url=config.discord_webhook, rate_limit_retry=True)

message_config = {
SafetyToolsLevels.RED: {
# https://colorcodes.io/red/fire-truck-red-color-codes/
"color": "CE2029",
"description": "Red",
}
}

embed = DiscordEmbed(
title=f'Safetytools Usage ({ message_config[level]["description"] })',
description=f"[Link]({__generate_url(config.xenforo_base_url, post_id, thread_id, position)})",
color=message_config[level]["color"],
)
embed.add_embed_field(name="Post Author", value=post_user)
embed.add_embed_field(name="Reaction User(s)", value=", ".join(reaction_users))

webhook.add_embed(embed)

response = webhook.execute()

succeeded = False
if response.status_code != 200:
LOGGER.error(
f"Discord Webhook (Safetytools Notification) failed with status code {response.status_code}"
)
else:
LOGGER.info("Discord Webhook (Safetytools Notification) succeeded.")
succeeded = True

return succeeded
7 changes: 7 additions & 0 deletions telathbot/enums.py
@@ -0,0 +1,7 @@
from enum import Enum


class SafetyToolsLevels(str, Enum):
RED = "red"
YELLOW = "yellow"
GREEN = "green"
1 change: 1 addition & 0 deletions telathbot/models/__init__.py
@@ -1 +1,2 @@
from .metadata import Metadata
from .safetytools import SafetyToolsUse
17 changes: 17 additions & 0 deletions telathbot/models/safetytools.py
@@ -0,0 +1,17 @@
from umongo import Document, fields

from telathbot.constants import SAFETYTOOLS_COLLECTION
from telathbot.databases.mongo import UMONGO


@UMONGO.register
class SafetyToolsUse(Document): # pylint: disable=abstract-method
class Meta:
collection_name = SAFETYTOOLS_COLLECTION

postId = fields.IntegerField()
threadId = fields.IntegerField()
postUser = fields.StrField()
reactionUsers = fields.StrField()
notified = fields.BooleanField()
dateObserved = fields.DateTimeField()
7 changes: 4 additions & 3 deletions telathbot/routers/metadata.py
Expand Up @@ -31,7 +31,7 @@ async def get_metadata() -> MetadataSchema:
"""
Application metadata
"""
metadata = await Metadata.find_one()
metadata = await Metadata.find_one({"type": "metadata"})
response = MetadataSchema(**metadata.to_mongo())

return response
Expand All @@ -42,7 +42,7 @@ async def check_ip(ip: MetadataCheckIPRequest) -> MetadataCheckIPResponse:
"""
Checks if IP is still valid. Will send a Discord notification if not.
"""
metadata = await Metadata.find_one()
metadata = await Metadata.find_one({"type": "metadata"})

if not ip.ip:
public_ip = str(await get_ip_address())
Expand All @@ -52,7 +52,8 @@ async def check_ip(ip: MetadataCheckIPRequest) -> MetadataCheckIPResponse:
if metadata.lastPublicIp != public_ip:
webhook_status = send_ip_changed_notification(new_ip=public_ip)
response = MetadataCheckIPResponse(changed=True, webhook_status=webhook_status)

metadata.update({"lastPublicIp": public_ip})
await metadata.commit()
else:
response = MetadataCheckIPResponse(changed=False, webhook_status=False)

Expand Down

0 comments on commit 24eae75

Please sign in to comment.