def patreon_sync_post(): if "patreon" not in session: abort(401) api_client = patreon.API(session["patreon"]["access_token"]) user_response = api_client.fetch_user( None, { 'pledge': [ "amount_cents", "total_historical_amount_cents", "declined_since", "created_at", "pledge_cap_cents", "patron_pays_fees", "outstanding_payment_amount_cents" ] }) user = user_response.data() if not (user): abort(403) usr = format_patreon_user(user) if usr["titan"]["eligible_tokens"] <= 0: return ('', 402) dbpatreon = db.session.query(Patreon).filter( Patreon.user_id == usr["id"]).first() if not dbpatreon: dbpatreon = Patreon(usr["id"]) dbpatreon.total_synced = usr["titan"]["total_cents_pledged"] db.session.add(dbpatreon) set_titan_token( session["user_id"], usr["titan"]["eligible_tokens"], "PATREON {} [{}]".format(usr["attributes"]["full_name"], usr["id"])) add_badge(session["user_id"], "supporter") session["tokens"] = get_titan_token(session["user_id"]) return ('', 204)
def index(): if User.query.count() == 0: load_config() return render_template("setup.html") projects = sorted(Project.query.all(), key=lambda p: p.name) avatar = "//www.gravatar.com/avatar/" + hashlib.md5( _cfg("your-email").encode("utf-8")).hexdigest() selected_project = request.args.get("project") if selected_project: try: selected_project = int(selected_project) except: selected_project = None active_recurring = (Donation.query.filter( Donation.type == DonationType.monthly).filter( Donation.active == True).filter(Donation.hidden == False)) recurring_count = active_recurring.count() recurring_sum = sum([d.amount for d in active_recurring]) access_token = _cfg("patreon-access-token") campaign = _cfg("patreon-campaign") if access_token and campaign: try: import patreon client = patreon.API(access_token) campaign = client.fetch_campaign() attrs = campaign.json_data["data"][0]["attributes"] patreon_count = attrs["patron_count"] patreon_sum = attrs["pledge_sum"] except: patreon_count = 0 patreon_sum = 0 else: patreon_count = 0 patreon_sum = 0 liberapay = _cfg("liberapay-campaign") if liberapay: lp = (requests.get( "https://liberapay.com/{}/public.json".format(liberapay))).json() lp_count = lp['npatrons'] lp_sum = int(float(lp['receiving']['amount']) * 100) # Convert from weekly to monthly lp_sum = lp_sum * 52 // 12 else: lp_count = 0 lp_sum = 0 return render_template("index.html", projects=projects, avatar=avatar, selected_project=selected_project, recurring_count=recurring_count, recurring_sum=recurring_sum, patreon_count=patreon_count, patreon_sum=patreon_sum, lp_count=lp_count, lp_sum=lp_sum, currency=currency)
def authenticate(self): """Authenticate with Patreon API""" oauth_client = patreon.OAuth(self.client_id, self.client_secret) tokens = oauth_client.get_tokens(request.args.get('code'), '/oauth/redirect') access_token = tokens['access_token'] api_client = patreon.API(access_token) return api_client
def getApiClient(self, request): """ Called after callback was triggered to fetch acccess_token and API instance. Returns (token, api) """ oauth_client = patreon.OAuth(self.client_id, self.client_secret) tokens = oauth_client.get_tokens(request.query.code, self.callback) access_token = tokens['access_token'] return access_token, patreon.API(access_token)
def patreon_callback(): headers = { "User-Agent": user_agent_string(), "Content-Type": "application/x-www-form-urlencoded" } params = { "code": request.args.get('code'), "grant_type": "authorization_code", "client_id": config.patreon_id, "client_secret": config.patreon_secret, "redirect_uri": config.patreon_redirect } r = requests.post(config.patreon_token_url, headers=headers, data=params) session['patreon_oauth2_token'] = r.json()['access_token'] session['patreon_refresh_token'] = r.json()['refresh_token'] api_client = patreonlib.API(session['patreon_oauth2_token']) user_response = api_client.fetch_user() user = user_response.data() session['patreon_user_id'] = user.id() pledges = user.relationship('pledges') pledge = pledges[0] if pledges and len(pledges) > 0 else None headers = { "User-Agent": user_agent_string(), "Content-Type": "application/x-www-form-urlencoded" } params = { "grant_type": "refresh_token", "refresh_token": session['patreon_refresh_token'], "client_id": config.patreon_id, "client_secret": config.patreon_secret } r = requests.post(config.patreon_token_url, headers=headers, data=params) session['access_token'] = r.json()['access_token'] session['refresh_token'] = r.json()['refresh_token'] if pledge is not None: if pledge['attributes']['declined_since'] is None: if pledge['attributes']['amount_cents'] == 100: session['pledge'] = 1 elif pledge['attributes']['amount_cents'] == 500: session['pledge'] = 2 return check_pledge() else: del session['patreon_oauth2_token'] return redirect('/nopledge')
def patreon_payout(): # Only perform on day 1 of a month if not datetime.now().day == 1: log.debug("Not first day of the month, not paying out patrons.") return None first_run = False if not os.path.exists(PAYOUTS_FILE_PATH): write_config('payouts', {'last_payout_month': datetime.now().month}) first_run = True payout_data = read_config("payouts") if datetime.now().month != payout_data['last_payout_month'] or first_run: log.info("Paying out patrons...") api_client = patreon.API(read_config("config")["patreon_token"]) pledges = {} users = {} all_data = api_client.fetch_campaign_and_patrons( )._all_resource_json_data() for data in all_data: if 'type' in data: if data['type'] == 'pledge': pledges[data['relationships']['patron']['data'] ['id']] = data['attributes'] elif data['type'] == 'user': users[data['id']] = data['attributes'] user_info = read_config("players") for user_id, pledge in pledges.items(): active = pledge['declined_since'] == None log.info( f"{users[user_id]['email']} is paying {pledge['amount_cents'] / 100}$, active is {active}" ) if user_info[users[user_id]['email']] == None: log.warning( f"Tried to payout user with email {users[user_id]['email']} but it does not have SteamID set." ) broadcast( "There was a problem during payout to one of the patrons, SteamID not set, please contact administrator.", True) continue if not active: log.warning( f"User {users[user_id]['email']} canceled subscription. Not paying." ) continue rcon_command( f"ScriptCommand TCsAR AddArcTotal {user_info[users[user_id]['email']]} {pledge['amount_cents'] / 100}" ) else: log.debug( "Not paying out patrons because it's the same month as we payed already." )
def patreon_sync_get(): if "patreon" not in session: return redirect(url_for("user.patreon_landing")) api_client = patreon.API(session["patreon"]["access_token"]) user_response = api_client.fetch_user(None, { 'pledge': ["amount_cents", "total_historical_amount_cents", "declined_since", "created_at", "pledge_cap_cents", "patron_pays_fees", "outstanding_payment_amount_cents"] }) user = user_response.data() if not (user): del session["patreon"] return redirect(url_for("user.patreon_landing")) return render_template("patreon.html.j2", state="prepare", user=format_patreon_user(user))
async def renew(self): async with self.pool.acquire() as connection: for user in await connection.fetch('SELECT * FROM premium'): if user['check'] is False: return api_client = patreonlib.API(user['patreon_token']) user_response = api_client.fetch_user() patreon_user = user_response.data() pledges = patreon_user.relationship('pledges') pledge = pledges[0] if pledges and len(pledges) > 0 else None patreon_type = None if pledge is not None: if pledge['attributes']['declined_since'] is None: if pledge['attributes']['amount_cents'] == 100: patreon_type = 1 elif pledge['attributes']['amount_cents'] == 500: patreon_type = 2 else: statement = await connection.prepare( 'DELETE FROM premium WHERE user_id = $1') return await statement.fetchval(user['user_id']) headers = { "User-Agent": user_agent_string(), "Content-Type": "application/x-www-form-urlencoded" } params = { "grant_type": "refresh_token", "refresh_token": user['refresh_token'], "client_id": config.patreon_id, "client_secret": config.patreon_secret } r = requests.post(config.patreon_token_url, headers=headers, data=params) token = r.json()['access_token'] refresh_token = r.json()['refresh_token'] statement = await connection.prepare( 'UPDATE premium SET patreon_token = $1, refresh_token = $2, type = $3' ) await statement.fetchval(token, refresh_token, patreon_type) Timer(60 * 60 * 24, self.run_renew).start()
async def init(self, access_token): """Init the Patreon api @param str access_token -- @return None""" # Init the patreon api client if self.client is None: self.client = patreon.API(access_token) return
def get_patrons(): p_auth = PatreonAuth(PATREON_CONFIG_FILE) access_token = p_auth.auth() client = patreon.API(access_token=access_token) campaigns = client.get_campaigns(page_size=10) if not isinstance(campaigns, JSONAPIParser): raise Exception('Could not get campaigns') campaign_id = campaigns.data()[0].id() members = [] cursor = None while True: members_response = client.get_campaigns_by_id_members( campaign_id, page_size=10, cursor=cursor, fields={ 'member': [ patreon.schemas.member.Attributes.full_name, patreon. schemas.member.Attributes.currently_entitled_amount_cents, patreon.schemas.member.Attributes.email, patreon.schemas.member.Attributes.patron_status ] }) members += members_response.data() try: cursor = client.extract_cursor(members_response) except Exception as e: if type(e) == Exception: break # хак, чтобы либа завершила пагинацию raise res = [ PatronInfo( name=member.attribute('full_name'), email=member.attribute('email'), pledge_cents=member.attribute('currently_entitled_amount_cents'), ) for member in members if member.attribute('patron_status') == 'active_patron' ] return res
def handle(self, *args, **options): api_client = patreon.API(os.getenv('PATREON_ACCESS_TOKEN')) per_page = 20 processed = 0 pledges, cursor = api_client.fetch_page_of_pledges(318380, per_page, return_cursor=True) processed += self.process_pledges(pledges) while 'next' in pledges['links']: # Get the next page pledges, cursor = api_client.fetch_page_of_pledges( 318380, per_page, cursor, return_cursor=True) processed += self.process_pledges(pledges) assert processed == pledges['meta']['count']
def update_user_for_tokens(patreon_refresh_token, patreon_access_token): # https://www.patreon.com/platform/documentation/oauth -- Step 4 # Use the tokens to fetch the Patreon profile and pledge data, saving it all to the db. api_client = patreon.API(patreon_access_token) user_response = api_client.fetch_user() user = user_response.data() if not (patreon_refresh_token and patreon_access_token and user): return None db_user = get_or_create_user_for_patreon_user_id( patreon_user_data=user, patreon_refresh_token=patreon_refresh_token, patreon_access_token=patreon_access_token) pledges = user.relationship('pledges') if pledges and len(pledges) > 0: pledge = pledges[0] db_user.update( {'patreon_pledge_amount_cents': pledge.attribute('amount_cents')}) db.session.commit() return db_user
def page_patreon_oauth(): try: code = request.args.get('code') ckey = request.args.get('state') if code != None and ckey != None: oauth_client = patreon.OAuth( cfg.PRIVATE["patreon"]["client_id"], cfg.PRIVATE["patreon"]["client_secret"]) tokens = oauth_client.get_tokens( code, 'https://beestation13.com/patreonauth') access_token = tokens['access_token'] api_client = patreon.API(access_token) user_identity = api_client.get_identity().data() user_id = user_identity.id() player = db.Player.from_ckey(ckey) if not player: return redirect("/linkpatreon?error=invalidckey") db.site_db.link_patreon(ckey, user_id) return redirect("/linkpatreon?success=true") else: return redirect("/linkpatreon?error=unknown") except Exception as E: return str(E) return redirect("/linkpatreon?error=unknown")
#get the Patreon API in the script import patreon #verify client with token access_token = '<Your Token>' api_client = patreon.API(access_token) #Get the API to get information from 'campaign' campaign_response = api_client.fetch_campaign() #From that information we want the first item's id campaign_id = campaign_response.data()[0].id() #creating list where all patrons' information will be stored all_pledges = [] #cursor tells us if there are any pages left to paginate for us to know that we have to search through to get all patron names #if cursor = none, then there are no pages left cursor = None #printing a sentence to check if script is working properly until now since fetching all data might take some time print("Fetching Patron names...") #looping cursor until we have paginated all pages and thus have fetched all patron names while True: pledges_response = api_client.fetch_page_of_pledges( campaign_id, 25, cursor=cursor, fields={'pledge': ['declined_since']}) all_pledges += pledges_response.data() cursor = api_client.extract_cursor(pledges_response) #breaking out of loop when cursor = none, when there are no pages left
def patreon_payout(): # Only perform on day 1 of a month now = datetime.now() payout_data = read_config("patreon") log.info("Checking payout information...") payout_emails = [] for email, info in payout_data.items(): if now.month > info['last_payout_month'] and now > info[ 'last_payout_date']: log.info(f"User {email} added for payout check.") payout_emails.append(email) log.info(f"Payout emails {payout_emails}") if len(payout_emails) > 0: log.info(f"Gathering patreon api info...") api_client = patreon.API(read_config("config")["patreon_token"]) pledges = {} users = {} all_data = api_client.fetch_campaign_and_patrons( )._all_resource_json_data() for data in all_data: if 'type' in data: if data['type'] == 'pledge': pledges[data['relationships']['patron']['data'] ['id']] = data['attributes'] elif data['type'] == 'user': users[data['id']] = data['attributes'] user_info = read_config("players") for user_id, pledge in pledges.items(): active = pledge['declined_since'] == None if users[user_id]['email'] not in payout_emails: log.warning( f"User {users[user_id]['email']} already received payout this month. Skip." ) continue if user_info[users[user_id]['email']] == None: log.warning( f"Tried to payout user with email {users[user_id]['email']} but it does not have SteamID set." ) broadcast( "There was a problem during payout to one of the patrons, SteamID not set, please contact administrator.", True) continue if not active: log.warning( f"User {users[user_id]['email']} canceled subscription. Not paying." ) continue log.info( f"{users[user_id]['email']} is paying {pledge['amount_cents'] / 100}$, active is {active}" ) if users[user_id]['email'].strip() in payout_emails: log.info(f"Paying out user {users[user_id]['email'].strip()}") rcon_command( f"ScriptCommand TCsAR AddArcTotal {user_info[users[user_id]['email']]} {pledge['amount_cents'] / 100}" ) log.debug( f"Setting user payout date for {users[user_id]['email']}..." ) payout_data[users[user_id]['email']][ 'last_payout_month'] = datetime.now().month payout_data[users[user_id] ['email']]['last_payout_date'] = datetime.now() else: log.info( f"NOT paying out user {users[user_id]['email'].strip()} because it was not found in payout_emails - probably already payed." ) write_config('patreon', payout_data) else: log.info("Looks like everyone received their payment, exit.")
def index(): if User.query.count() == 0: load_config() return render_template("setup.html") projects = sorted(Project.query.all(), key=lambda p: p.name) if os.path.exists('static/logo.png'): avatar = os.path.join('static/logo.png') else: avatar = "//www.gravatar.com/avatar/" + hashlib.md5(_cfg("your-email").encode("utf-8")).hexdigest() selected_project = request.args.get("project") if selected_project: try: selected_project = int(selected_project) except: selected_project = None active_recurring = (Donation.query .filter(Donation.type == DonationType.monthly) .filter(Donation.active == True) .filter(Donation.hidden == False)) recurring_count = active_recurring.count() recurring_sum = sum([d.amount for d in active_recurring]) access_token = _cfg("patreon-access-token") campaign = _cfg("patreon-campaign") if access_token and campaign: try: import patreon client = patreon.API(access_token) campaign = client.fetch_campaign() attrs = campaign.json_data["data"][0]["attributes"] patreon_count = attrs["patron_count"] patreon_sum = attrs["pledge_sum"] except: import traceback traceback.print_exc() patreon_count = 0 patreon_sum = 0 else: patreon_count = 0 patreon_sum = 0 liberapay = _cfg("liberapay-campaign") if liberapay: lp = (requests .get("https://liberapay.com/{}/public.json".format(liberapay)) ).json() lp_count = lp['npatrons'] lp_sum = int(float(lp['receiving']['amount']) * 100) # Convert from weekly to monthly lp_sum = lp_sum * 52 // 12 else: lp_count = 0 lp_sum = 0 opencollective = _cfg("opencollective-campaign") if opencollective: oc = requests.get("https://opencollective.com/{}.json".format(opencollective)).json() oc_count = oc['backersCount'] oc_sum = int(oc['yearlyIncome']) # Convert from yearly to monthly oc_sum = oc_sum // 12 else: oc_count = 0 oc_sum = 0 github_token = _cfg("github-token") if github_token: query = """ { viewer { login sponsorsListing { tiers(first:100) { nodes { monthlyPriceInCents adminInfo { sponsorships(includePrivate:true) { totalCount } } } } } } } """ r = requests.post("https://api.github.com/graphql", json={ "query": query }, headers={ "Authorization": "bearer {}".format(github_token) }) result = r.json() nodes = result["data"]["viewer"]["sponsorsListing"]["tiers"]["nodes"] cnt = lambda n: n["adminInfo"]["sponsorships"]["totalCount"] gh_count = sum(cnt(n) for n in nodes) gh_sum = sum(n["monthlyPriceInCents"] * cnt(n) for n in nodes) gh_user = result["data"]["viewer"]["login"] else: gh_count = 0 gh_sum = 0 gh_user = 0 return render_template("index.html", projects=projects, avatar=avatar, selected_project=selected_project, recurring_count=recurring_count, recurring_sum=recurring_sum, patreon_count=patreon_count, patreon_sum=patreon_sum, lp_count=lp_count, lp_sum=lp_sum, gh_count=gh_count, gh_sum=gh_sum, gh_user=gh_user, oc_count=oc_count, oc_sum=oc_sum, currency=currency)
def index(): if User.query.count() == 0: load_config() return render_template("setup.html") projects = sorted(Project.query.all(), key=lambda p: p.name) if os.path.exists("static/logo.png"): avatar = os.path.join("static/logo.png") else: avatar = ("//www.gravatar.com/avatar/" + hashlib.md5(_cfg("your-email").encode("utf-8")).hexdigest()) selected_project = request.args.get("project") if selected_project: try: selected_project = int(selected_project) except Exception: current_app.logger.exception( "Error while trying to select project: %s" % selected_project, exc_info=True, ) selected_project = None active_recurring = (Donation.query.filter( Donation.type == DonationType.monthly).filter( Donation.active == True).filter(Donation.hidden == False)) recurring_count = active_recurring.count() recurring_sum = sum([d.amount for d in active_recurring]) limit = datetime.now() - timedelta(days=30) month_onetime = Donation.query.filter( Donation.type == DonationType.one_time).filter( Donation.created > limit) onetime_count = month_onetime.count() onetime_sum = sum([d.amount for d in month_onetime]) access_token = _cfg("patreon-access-token") campaign = _cfg("patreon-campaign") if access_token and campaign: try: import patreon client = patreon.API(access_token) campaign = client.fetch_campaign() attrs = campaign.json_data["data"][0]["attributes"] patreon_count = attrs["patron_count"] patreon_sum = attrs["pledge_sum"] except Exception as e: current_app.logger.warning("Error to get patreon information: %s" % e, exc_info=True) patreon_count = 0 patreon_sum = 0 else: patreon_count = 0 patreon_sum = 0 liberapay = _cfg("liberapay-campaign") if liberapay: try: lp = (requests.get( "https://liberapay.com/{}/public.json".format(liberapay), timeout=5)).json() except Exception: traceback.print_exc() print("Error while trying to get data from liberapay") lp_count = 0 lp_sum = 0 else: lp_count = lp["npatrons"] lp_sum = int(float(lp["receiving"]["amount"]) * 100) # Convert from weekly to monthly lp_sum = lp_sum * 52 // 12 else: lp_count = 0 lp_sum = 0 github_token = _cfg("github-token") if github_token: query = """ { viewer { login sponsorsListing { tiers(first:100) { nodes { monthlyPriceInCents adminInfo { sponsorships(includePrivate:true) { totalCount } } } } } } } """ r = requests.post( "https://api.github.com/graphql", json={"query": query}, headers={"Authorization": f"bearer {github_token}"}, ) result = r.json() nodes = result["data"]["viewer"]["sponsorsListing"]["tiers"]["nodes"] cnt = lambda n: n["adminInfo"]["sponsorships"]["totalCount"] gh_count = sum(cnt(n) for n in nodes) gh_sum = sum(n["monthlyPriceInCents"] * cnt(n) for n in nodes) gh_user = result["data"]["viewer"]["login"] else: gh_count = 0 gh_sum = 0 gh_user = 0 return render_template( "index.html", projects=projects, avatar=avatar, selected_project=selected_project, recurring_count=recurring_count, recurring_sum=recurring_sum, onetime_count=onetime_count, onetime_sum=onetime_sum, patreon_count=patreon_count, patreon_sum=patreon_sum, lp_count=lp_count, lp_sum=lp_sum, currency=currency, gh_count=gh_count, gh_sum=gh_sum, gh_user=gh_user, version=version(), )
def __init__(self, access_token): self._api = patreon.API(access_token)