From ac89e2e88625b9fa80c9f7ec82dd18e214ab449f Mon Sep 17 00:00:00 2001 From: mcinj <98779161+mcinj@users.noreply.github.com> Date: Thu, 5 May 2022 16:50:01 -0400 Subject: [PATCH] sqlite db - store entered giveaways into db - store notifications into db - future: add won notifications --- .dockerignore | 3 ++- .gitignore | 3 ++- requirements.txt | 5 ++++- src/SteamGifts.py | 16 +++++++++++--- src/giveaway.py | 4 ++++ src/notification.py | 17 ++++++++++---- src/run.py | 6 ++--- src/tables.py | 54 +++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 95 insertions(+), 13 deletions(-) create mode 100644 src/tables.py diff --git a/.dockerignore b/.dockerignore index 2095963..d74cc4b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,2 +1,3 @@ config/config.ini -config/debug.log \ No newline at end of file +config/debug.log +config/sqlite.db \ No newline at end of file diff --git a/.gitignore b/.gitignore index dee8e27..1599e04 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ venv/ __pycache__/ .idea config/config.ini -config/debug.log \ No newline at end of file +config/debug.log +config/sqlite.db \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 13d9626..f19567d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,6 @@ requests==2.27.1 beautifulsoup4==4.11.1 -urllib3==1.26.9 \ No newline at end of file +urllib3==1.26.9 +sqlalchemy==1.4.36 +sqlalchemy_utils==0.38.2 +pytz==2022.1 \ No newline at end of file diff --git a/src/SteamGifts.py b/src/SteamGifts.py index 62d0681..129c96a 100644 --- a/src/SteamGifts.py +++ b/src/SteamGifts.py @@ -1,14 +1,17 @@ import json +from datetime import datetime from random import randint from time import sleep import requests from bs4 import BeautifulSoup from requests.adapters import HTTPAdapter +from sqlalchemy.orm import Session from urllib3.util import Retry import log from giveaway import Giveaway +from tables import engine, TableGiveaway logger = log.get_logger(__name__) @@ -117,12 +120,19 @@ class SteamGifts: return True - def enter_giveaway(self, game_id): - payload = {'xsrf_token': self.xsrf_token, 'do': 'entry_insert', 'code': game_id} + def enter_giveaway(self, giveaway): + payload = {'xsrf_token': self.xsrf_token, 'do': 'entry_insert', 'code': giveaway.game_id} entry = requests.post('https://www.steamgifts.com/ajax.php', data=payload, cookies=self.cookie) json_data = json.loads(entry.text) if json_data['type'] == 'success': + g = TableGiveaway(name=giveaway.game_name, game_id=giveaway.game_id, entries=giveaway.game_entries, + giveaway_created=TableGiveaway.unix_timestamp_to_utc_datetime(giveaway.time_created_timestamp), + giveaway_ended=TableGiveaway.unix_timestamp_to_utc_datetime(giveaway.time_remaining_timestamp), + cost=giveaway.game_cost, copies=giveaway.copies, entered=True) + with Session(engine) as session: + session.add(g) + session.commit() return True def evaluate_giveaways(self, page=1): @@ -174,7 +184,7 @@ class SteamGifts: break if if_enter_giveaway: - res = self.enter_giveaway(giveaway.game_id) + res = self.enter_giveaway(giveaway) if res: self.points -= int(giveaway.game_cost) txt = f"🎉 One more game! Has just entered {giveaway.game_name}" diff --git a/src/giveaway.py b/src/giveaway.py index 1dbced8..7c13aeb 100644 --- a/src/giveaway.py +++ b/src/giveaway.py @@ -15,8 +15,10 @@ class Giveaway: self.game_cost = None self.game_entries = None self.copies = None + self.time_created_timestamp = None self.time_remaining_string = None self.time_remaining_in_minutes = None + self.time_remaining_timestamp = None self.time_created_string = None self.time_created_in_minutes = None @@ -27,8 +29,10 @@ class Giveaway: self.game_cost, self.copies = self.determine_cost_and_copies(self.soup_item, self.game_name, self.game_id) self.game_entries = int(soup_item.select('div.giveaway__links span')[0].text.split(' ')[0].replace(',', '')) times = soup_item.select('div span[data-timestamp]') + self.time_remaining_timestamp = int(times[0]['data-timestamp']) self.time_remaining_string = times[0].text self.time_remaining_in_minutes = self.determine_time_in_minutes(times[0]['data-timestamp']) + self.time_created_timestamp = int(times[1]['data-timestamp']) self.time_created_string = times[1].text self.time_created_in_minutes = self.determine_time_in_minutes(times[1]['data-timestamp']) diff --git a/src/notification.py b/src/notification.py index b110581..00232be 100644 --- a/src/notification.py +++ b/src/notification.py @@ -1,6 +1,9 @@ import http.client import urllib +from sqlalchemy.orm import Session + +from tables import engine, TableNotification import log logger = log.get_logger(__name__) @@ -14,11 +17,11 @@ class Notification: self.pushover_user_key = None self.message_prefix = "SG-bot: " - def send(self, message): + def send(self, type_of_error, message): logger.debug(f"Attempting to notify: {message}") if self.pushover: logger.debug("Pushover enabled. Sending message.") - self.__pushover(message) + self.__pushover(type_of_error, message) def enable_pushover(self, token, user_key): logger.debug("Enabling pushover notifications.") @@ -26,7 +29,7 @@ class Notification: self.pushover_token = token self.pushover_user_key = user_key - def __pushover(self, message): + def __pushover(self, type_of_error, message): conn = http.client.HTTPSConnection("api.pushover.net:443") conn.request("POST", "/1/messages.json", urllib.parse.urlencode({ @@ -36,7 +39,13 @@ class Notification: }), {"Content-type": "application/x-www-form-urlencoded"}) response = conn.getresponse() logger.debug(f"Pushover response code: {response.getcode()}") - if response.getcode() != 200: + if response.getcode() == 200: + n = TableNotification(type=type_of_error, message=f"{message}", medium='pushover', success=True) + else: logger.error(f"Pushover notification failed. Code {response.getcode()}: {response.read().decode()}") + n = TableNotification(type=type_of_error, message=f"{message}", medium='pushover', success=False) + with Session(engine) as session: + session.add(n) + session.commit() diff --git a/src/run.py b/src/run.py index e74038b..57d03d2 100644 --- a/src/run.py +++ b/src/run.py @@ -6,11 +6,11 @@ from ConfigReader import ConfigReader, ConfigException from SteamGifts import SteamGifts, SteamGiftsException from notification import Notification + logger = log.get_logger(__name__) def run(): - file_name = '../config/config.ini' config = None try: @@ -68,12 +68,12 @@ def run(): logger.info(f"Going to sleep for {random_seconds / 60} minutes.") sleep(random_seconds) except SteamGiftsException as e: - notification.send(e) + notification.send('error', e) sleep(5) exit(-1) except Exception as e: logger.error(e) - notification.send("Something happened and the bot had to quit!") + notification.send('error', "Something happened and the bot had to quit!") sleep(5) exit(-1) diff --git a/src/tables.py b/src/tables.py new file mode 100644 index 0000000..47fff18 --- /dev/null +++ b/src/tables.py @@ -0,0 +1,54 @@ +from sqlalchemy import create_engine, Integer, String, Column, Table, \ + MetaData, DateTime, Numeric, Enum, Boolean, TIMESTAMP, func +from sqlalchemy_utils import database_exists, create_database +from sqlalchemy.orm import registry +from datetime import datetime +import pytz + +mapper_registry = registry() +mapper_registry.metadata +Base = mapper_registry.generate_base() +engine = create_engine('sqlite:///../config/sqlite.db', echo=True) + + +class TableNotification(Base): + __tablename__ = 'notification' + id = Column(Integer, primary_key=True, nullable=False) + type = Column(String(50), nullable=False) + message = Column(String(300), nullable=False) + medium = Column(String(50), nullable=False) + success = Column(Boolean, nullable=False) + created_at = Column(DateTime(timezone=True), server_default=func.now()) + + __mapper_args__ = {"eager_defaults": True} + + +class TableGiveaway(Base): + __tablename__ = 'giveaway' + id = Column(Integer, primary_key=True, nullable=False) + name = Column(String(200), nullable=False) + game_id = Column(String(10), nullable=False) + entries = Column(Integer(), nullable=False) + giveaway_created = Column(DateTime(timezone=True), nullable=False) + giveaway_ended = Column(DateTime(timezone=True), nullable=False) + cost = Column(Integer(), nullable=False) + copies = Column(Integer(), nullable=False) + entered = Column(Boolean(), nullable=False) + created_at = Column(DateTime(timezone=True), server_default=func.now()) + added_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now()) + + __mapper_args__ = {"eager_defaults": True} + + @classmethod + def unix_timestamp_to_utc_datetime(cls, timestamp): + return datetime.utcfromtimestamp(timestamp) + + +if not database_exists(engine.url): + create_database(engine.url) + # emitting DDL + mapper_registry.metadata.create_all(engine) + Base.metadata.create_all(engine) +else: + # Connect the database if exists. + engine.connect() \ No newline at end of file