diff --git a/drama/__main__.py b/drama/__main__.py index 8f1cc2182..f90e7c783 100644 --- a/drama/__main__.py +++ b/drama/__main__.py @@ -175,7 +175,8 @@ def retry(f): return f(self, *args, **kwargs) except OperationalError as e: #self.session.rollback() - raise(DatabaseOverload) + #raise(DatabaseOverload) + abort(500) except: self.session.rollback() return f(self, *args, **kwargs) diff --git a/drama/classes/__init__.py b/drama/classes/__init__.py index e235f06b7..d833cadeb 100644 --- a/drama/classes/__init__.py +++ b/drama/classes/__init__.py @@ -16,5 +16,5 @@ from .domains import * from .subscriptions import * from .ips import * from .titles import * -from .paypal import * +from .award import * from .mod_logs import * \ No newline at end of file diff --git a/drama/classes/award.py b/drama/classes/award.py new file mode 100644 index 000000000..40e93c4bb --- /dev/null +++ b/drama/classes/award.py @@ -0,0 +1,49 @@ +#import requests +#from os import environ +from sqlalchemy import * +from sqlalchemy.orm import relationship +#from .mix_ins import * +from drama.__main__ import Base, app + +AWARDS = { + "ban": { + "title": "1-Day Ban", + "description": "Ban the author for a day.", + "icon": "fas fa-gavel", + "color": "text-danger" + }, + "shit": { + "title": "Literal Shitpost", + "description": "Let OP know how much their post sucks ass.", + "icon": "fas fa-poop", + "color": "text-black-50" + } +} + + +class AwardRelationship(Base): + + __tablename__ = "award_relationships" + + id = Column(Integer, primary_key=True) + + user_id = Column(Integer, ForeignKey("users.id")) + submission_id = Column(Integer, ForeignKey("submissions.id"), default=None) + comment_id = Column(Integer, ForeignKey("comments.id"), default=None) + kind = Column(String(20)) + + user = relationship("User", primaryjoin="AwardRelationship.user_id==User.id", lazy="joined") + post = relationship( + "Submission", + primaryjoin="AwardRelationship.submission_id==Submission.id", + lazy="joined" + ) + comment = relationship( + "Comment", + primaryjoin="AwardRelationship.comment_id==Comment.id", + lazy="joined" + ) + + @property + def type(self): + return AWARDS[self.kind] diff --git a/drama/classes/paypal.py b/drama/classes/paypal.py deleted file mode 100644 index 59fd94a1e..000000000 --- a/drama/classes/paypal.py +++ /dev/null @@ -1,275 +0,0 @@ -import requests -from os import environ -from sqlalchemy import * -from sqlalchemy.orm import relationship -from .mix_ins import * -from drama.__main__ import Base, app - -PAYPAL_ID=environ.get("PAYPAL_CLIENT_ID", "").strip() -PAYPAL_SECRET=environ.get("PAYPAL_CLIENT_SECRET", "").strip() -PAYPAL_WEBHOOK_ID=environ.get("PAYPAL_WEBHOOK_ID", "").strip() - -PAYPAL_URL="https://api.paypal.com" - -STATUSES={ - 1:"CREATED", - 2:"AUTHORIZED", - 3:"CAPTURED", - -2:"REVERSED" -} - -class PayPalClient(): - - def __init__(self): - - self.paypal_token=None - self.token_expires=0 - self.webhook_id=PAYPAL_WEBHOOK_ID - - def print(self, x): - - try: - print(x) - except OSError: - pass - - def new_token(self): - - url=f"{PAYPAL_URL}/v1/oauth2/token" - - headers={ - "Accept":"application/json" - } - - data={ - "grant_type":"client_credentials" - } - - x=requests.post(url, headers=headers, data=data, auth=(PAYPAL_ID,PAYPAL_SECRET)) - - x=x.json() - - self.paypal_token=x["access_token"] - self.token_expires=int(time.time())+int(x["expires_in"]) - - def _get(self, url): - - if time.time()>self.token_expires: - self.new_token() - - url=PAYPAL_URL+url - - headers={ - "Content-Type":"application/json", - # "Accept":"application/json", - "Authorization":f"Bearer {self.paypal_token}" - } - - return requests.get(url, headers=headers) - - - def _post(self, url, data=None): - - if time.time()>self.token_expires: - self.new_token() - - url=PAYPAL_URL+url - - headers={ - "Content-Type":"application/json", - # "Accept":"application/json", - "Authorization":f"Bearer {self.paypal_token}" - } - - return requests.post(url, headers=headers, json=data) - - def create(self, txn): - - if not txn.id: - raise ValueError("txn must be flushed first") - - url="/v2/checkout/orders" - - data={ - "intent":"CAPTURE", - "purchase_units": - [ - { - "amount": { - "currency_code":"USD", - "value": str(txn.usd_cents/100) - } - } - ], - "application_context":{ - "return_url":f"https://{app.config['SERVER_NAME']}/shop/buy_coins_completed?txid={txn.base36id}" - } - } - - r=self._post(url, data=data) - - x=r.json() - - if x["status"]=="CREATED": - txn.paypal_id=x["id"] - txn.status=1 - - def authorize(self, txn): - - url=f"{txn.paypal_url}/authorize" - - x= self._post(url) - x=x.json() - - status=x["status"] - if status in ["SAVED", "COMPLETED"]: - txn.status=2 - - return x["status"] in ["SAVED", "COMPLETED"] - - - def capture(self, txn): - - url=f"{txn.paypal_url}/capture" - - x=self._post(url) - x=x.json() - - try: - status=x["status"] - if status=="COMPLETED": - txn.status=3 - except KeyError: - abort(403) - - return status=="COMPLETED" - - -class PayPalTxn(Base, Stndrd, Age_times): - - __tablename__="paypal_txns" - - id=Column(Integer, primary_key=True) - user_id=Column(Integer, ForeignKey("users.id")) - created_utc=Column(Integer) - paypal_id=Column(String) - usd_cents=Column(Integer) - coin_count=Column(Integer) - promo_id=Column(Integer, ForeignKey("promocodes.id")) - - status=Column(Integer, default=0) #0=initialized 1=created, 2=authorized, 3=captured, -1=failed, -2=reversed - - user=relationship("User", lazy="joined") - promo=relationship("PromoCode", lazy="joined") - - @property - def approve_url(self): - - return f"https://www.paypal.com/checkoutnow?token={self.paypal_id}" - - @property - def paypal_url(self): - - return f"/v2/checkout/orders/{self.paypal_id}" - - @property - def permalink(self): - return f"/paypaltxn/{self.base36id}" - - @property - def display_usd(self): - s=str(self.usd_cents) - d=s[0:-2] or '0' - c=s[-2:] - return f"${d}.{c}" - - @property - def status_text(self): - return STATUSES[self.status] - -class PromoCode(Base): - - __tablename__="promocodes" - - id=Column(Integer, primary_key=True) - code=Column(String(64)) - is_active=Column(Boolean) - percent_off=Column(Integer, default=None) - flat_cents_off=Column(Integer, default=None) - flat_cents_min=Column(Integer, default=None) - promo_start_utc=Column(Integer, default=None) - promo_end_utc=Column(Integer, default=None) - promo_info=Column(String(64), default=None) - - def adjust_price(self, cents): - - now=int(time.time()) - - if self.promo_start_utc and now < self.promo_start_utc: - return cents - - elif self.promo_end_utc and now > self.promo_end_utc: - return cents - - if not self.is_active: - return cents - - if self.percent_off: - x = (100-self.percent_off)/100 - return int(cents * x) - - if self.flat_cents_off: - if cents >= self.flat_cents_min: - cents -= self.flat_cents_off - return cents - - else: - return cents - - @property - def display_flat_off(self): - s=str(self.flat_cents_off) - d=s[0:-2] or '0' - c=s[-2:] - return f"${d}.{c}" - - @property - def display_flat_min(self): - s=str(self.flat_cents_min) - d=s[0:-2] or '0' - c=s[-2:] - return f"${d}.{c}" - - @property - def promo_text(self): - - now=int(time.time()) - - if self.promo_start_utc and now < self.promo_start_utc: - return f"This promotion hasn't started yet. Try again later." - - elif self.promo_end_utc and now > self.promo_end_utc: - return f"This promotion has already ended. Sorry about that." - - elif self.percent_off: - text= f"Save {self.percent_off}% on all purchases with code {self.code}." - - elif self.flat_cents_off and self.flat_cents_min: - text= f"Save {self.display_flat_off} on any purchase over {self.display_flat_min} with code {self.code}." - - if self.promo_info: - text += f" Your purchase will also support {self.promo_info}." - - return text - - - -class AwardRelationship(Base): - - __tablename__="award_relationships" - - id=Column(Integer, primary_key=True) - - user_id=Column(Integer, ForeignKey("users.id")) - submission_id=Column(Integer, ForeignKey("submissions.id"), default=None) - comment_id=Column(Integer, ForeignKey("comments.id"), default=None) \ No newline at end of file diff --git a/drama/classes/user.py b/drama/classes/user.py index 4e6a5e3db..414d0df88 100644 --- a/drama/classes/user.py +++ b/drama/classes/user.py @@ -14,7 +14,6 @@ from .subscriptions import * from .userblock import * from .badges import * from .clients import * -from .paypal import PayPalTxn from drama.__main__ import Base, cache from drama.helpers.security import * @@ -155,11 +154,6 @@ class User(Base, Stndrd, Age_times): lazy="dynamic", primaryjoin="User.id==SaveRelationship.user_id") - _transactions = relationship( - "PayPalTxn", - lazy="dynamic", - primaryjoin="PayPalTxn.user_id==User.id") - # properties defined as SQL server-side functions referral_count = deferred(Column(Integer, server_default=FetchedValue())) follower_count = deferred(Column(Integer, server_default=FetchedValue())) @@ -934,11 +928,6 @@ class User(Base, Stndrd, Age_times): def boards_modded_ids(self): return [x.id for x in self.boards_modded] - @property - def txn_history(self): - - return self._transactions.filter(PayPalTxn.status != 1).order_by(PayPalTxn.created_utc.desc()).all() - @property def json_admin(self): data = self.json_raw