Skip to content

Commit

Permalink
Bump to 0.2.1: Add action history to avoid making multiple posterity …
Browse files Browse the repository at this point in the history
…comments per post
  • Loading branch information
kdknigga committed Jul 14, 2024
1 parent 3f8c7e3 commit 53c213e
Show file tree
Hide file tree
Showing 9 changed files with 274 additions and 3 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ PRAW_CLIENT_SECRET=""
PRAW_USERNAME=""
PRAW_PASSWORD=""
SUBREDDIT=""
DB_CONNECTION_STRING="sqlite+aiosqlite:///:memory:"
160 changes: 159 additions & 1 deletion poetry.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "rflying_tower_bot"
version = "0.2.0"
version = "0.2.1"
description = ""
authors = ["Kris Knigga <[email protected]>"]

Expand All @@ -11,6 +11,7 @@ pydantic-yaml = "^1.3.0"
aiohttp = "^3.9.5"
pydantic = "^2.8.2"
python-dotenv = "^1.0.1"
sqlalchemy = {extras = ["asyncio"], version = "^2.0.31"}

[tool.poetry.group.dev.dependencies]
pre-commit = "^3.7.1"
Expand Down
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ attrs==23.2.0 ; python_version >= "3.12" and python_version < "4.0"
certifi==2024.7.4 ; python_version >= "3.12" and python_version < "4.0"
charset-normalizer==3.3.2 ; python_version >= "3.12" and python_version < "4.0"
frozenlist==1.4.1 ; python_version >= "3.12" and python_version < "4.0"
greenlet==3.0.3 ; python_version >= "3.12" and python_version < "4.0"
idna==3.7 ; python_version >= "3.12" and python_version < "4.0"
importlib-metadata==8.0.0 ; python_version >= "3.12" and python_version < "4.0"
multidict==6.0.5 ; python_version >= "3.12" and python_version < "4.0"
Expand All @@ -19,6 +20,7 @@ python-dotenv==1.0.1 ; python_version >= "3.12" and python_version < "4.0"
requests==2.32.3 ; python_version >= "3.12" and python_version < "4.0"
ruamel-yaml-clib==0.2.8 ; platform_python_implementation == "CPython" and python_version < "3.13" and python_version >= "3.12"
ruamel-yaml==0.18.6 ; python_version >= "3.12" and python_version < "4.0"
sqlalchemy[asyncio]==2.0.31 ; python_version >= "3.12" and python_version < "4.0"
typing-extensions==4.12.2 ; python_version >= "3.12" and python_version < "4.0"
update-checker==0.18.0 ; python_version >= "3.12" and python_version < "4.0"
urllib3==2.2.2 ; python_version >= "3.12" and python_version < "4.0"
Expand Down
2 changes: 1 addition & 1 deletion rflying_tower_bot/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""rflying_tower_bot package."""

__version__ = "0.2.0"
__version__ = "0.2.1"
2 changes: 2 additions & 0 deletions rflying_tower_bot/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ async def main() -> None:
) as reddit:
bot_config = BotConfig(reddit)

await bot_config.history.initialize_db()

await bot_config.update_rules()

modlog = ModLog(bot_config)
Expand Down
4 changes: 4 additions & 0 deletions rflying_tower_bot/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from pydantic_yaml import parse_yaml_raw_as, to_yaml_str # type: ignore

from rflying_tower_bot import __version__ as bot_version
from rflying_tower_bot.history import History
from rflying_tower_bot.ruleset_schemas import (
PostFlairSettings,
RemovalReasonSettings,
Expand Down Expand Up @@ -41,6 +42,9 @@ def __init__(self, reddit: Reddit) -> None:
self.subreddit_name: str = os.getenv("SUBREDDIT", "flying")
self.rules_wiki_page = "botconfig/rflying_tower_bot"
self.rules: Ruleset | None = None
self.history = History(
os.getenv("DB_CONNECTION_STRING", "sqlite+aiosqlite:///:memory:")
)

async def update_rules(self) -> None:
"""Trigger the bot to fetch rules from the subreddit's wiki."""
Expand Down
98 changes: 98 additions & 0 deletions rflying_tower_bot/history.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
"""Keep track of action history."""

import datetime
import logging

from sqlalchemy import DateTime, String, func, insert, select
from sqlalchemy.ext.asyncio import AsyncAttrs, async_sessionmaker, create_async_engine
from sqlalchemy.orm import DeclarativeBase, mapped_column


class Base(AsyncAttrs, DeclarativeBase): # noqa: D101
pass


class HistoryTable(Base):
"""Represents a table for storing action history."""

__tablename__ = "history"

url = mapped_column(String, primary_key=True)
action = mapped_column(String, primary_key=True)
time = mapped_column(DateTime)


class History:
"""Keep track of action history."""

def __init__(
self, db_connection_string: str = "sqlite+aiosqlite:///:memory:"
) -> None:
"""
Initialize the History class.
Args:
----
db_connection_string (str, optional): The database connection string. Defaults to "sqlite+aiosqlite:///:memory:".
"""
self.log: logging.Logger = logging.getLogger(
f"{__name__}.{self.__class__.__name__}"
)

self.db = create_async_engine(db_connection_string, echo=False)

async def initialize_db(self) -> None:
"""Initialize the database."""
self.log.info("Initializing database: %s", self.db.url)
async with self.db.begin() as conn:
await conn.run_sync(Base.metadata.create_all)

async def check(self, url: str, action: str) -> int:
"""
Check the number of occurrences of a specific action for a given URL.
Args:
----
url (str): The URL to check.
action (str): The action to check.
Returns:
-------
int: The number of occurrences of the action for the URL.
"""
async_session = async_sessionmaker(self.db, expire_on_commit=False)
async with async_session() as session:
stmt = (
select(func.count(HistoryTable.url))
.where(HistoryTable.url == url)
.where(HistoryTable.action == action)
)
n = await session.scalar(stmt)
if n is not None:
return n
return 0

async def add(self, url: str, action: str) -> None:
"""
Add a new entry to the history.
Args:
----
url (str): The URL to add.
action (str): The action to add.
Returns:
-------
None
"""
self.log.debug('Inserting url "%s" into history', url)
async_session = async_sessionmaker(self.db, expire_on_commit=False)
async with async_session() as session:
stmt = insert(HistoryTable).values(
url=url, action=action, time=datetime.datetime.now()
)
await session.execute(stmt)
await session.commit()
5 changes: 5 additions & 0 deletions rflying_tower_bot/post_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ async def watch_poststream(self) -> None:
)
self.log.info("Watching the post stream for new posts in %s", subreddit)
async for post in subreddit.stream.submissions():
if await self.config.history.check(post.permalink, "save_post_body") > 0:
self.log.info("Skipping post %s, already processed", post.permalink)
continue

self.log.info("New post from %s: %s", post.author, post.permalink)
if post.selftext != "":
comment_text = f"This is a copy of the original post body for posterity:\n\n --- \n{post.selftext}"
Expand All @@ -45,6 +49,7 @@ async def watch_poststream(self) -> None:
)
return
await c.mod.distinguish(sticky=False)
await self.config.history.add(post.permalink, "save_post_body")
self.log.info(
"Comment created with post body for posterity: %s", c.permalink
)

0 comments on commit 53c213e

Please sign in to comment.