reformat, add setup.py

This commit is contained in:
simon987 2020-12-27 09:21:30 -05:00
parent 5c295ab1d8
commit 89ce04d3d1
18 changed files with 107 additions and 87 deletions

4
.gitignore vendored
View File

@ -1 +1,3 @@
parler/__pycache__/
parler/__pycache__/
.idea/
*.pyc

View File

@ -1,30 +1,31 @@
import uuid
class AuthenticationAPI:
def __init__(self, session, root_url="http://api.parler.com"):
self.root_url = root_url
self.s = session
def add_password_to_account(self, password, passwordConfirm):
'''
"""
POST /v1/login/passwordSetup
params:
password
passwordConfirm
passwordConfirm
response:
400: {"message": "This person already has a password set, and can not be set through this API"}
rate-limit: 5
auth: yes
'''
"""
return self.s.post(
"{}/v1/login/passwordSetup".format(self.root_url),
"{}/v1/login/passwordSetup".format(self.root_url),
data={
'password': password,
'passwordConfirm': passwordConfirm
})
def authenticate(self, email, password, captchaToken, captchaValue, deviceId=None):
'''
"""
POST /v1/login
params:
email
@ -37,12 +38,12 @@ class AuthenticationAPI:
response:
rate-limit: 5
auth: no
'''
"""
if deviceId is None:
deviceId = str(uuid.uuid4())
return self.s.post(
"{}/v1/login".format(self.root_url),
"{}/v1/login".format(self.root_url),
data={
'email': email,
'password': password,
@ -52,19 +53,19 @@ class AuthenticationAPI:
})
def begin_registration_otp(self):
'''
GET /v1/login/otp/registration
"""
GET /v1/login/otp/registration
returns OTP token as base64 QR code and secret
response:
200: {"message": "NEED_REG", "registration": "data:image/png;base64,...", "secret": "O5ZW..."}
200: {"message": "OK"} - if already added
rate-limit: 5
auth: yes
'''
"""
return self.s.get("{}/v1/login/otp/registration".format(self.root_url))
def change_password(self, password, new_password):
'''
"""
PATCH /v1/profile
params:
passwordOld
@ -74,26 +75,26 @@ class AuthenticationAPI:
400: { "message": "The provided name and password provided do not match", "fieldvalidationsMap": [] }
rate-limit: 4
auth: yes
'''
"""
return self.s.patch(
"{}/v1/profile".format(self.root_url),
"{}/v1/profile".format(self.root_url),
data={
'passwordOld': password,
'passwordNew': new_password,
'passwordConfirmation': new_password
})
def checkin(self):
'''
"""
GET /v1/checkin
removed
'''
"""
return self.s.get(
"{}/v1/checkin"
)
def create_account(self, email, password, captchaToken, captchaValue, deviceId=None):
'''
"""
POST /v1/login/register
removed, replaced by V2 API
params:
@ -108,12 +109,12 @@ class AuthenticationAPI:
captchaValue
response:
404: replaced by V2 Auth API
'''
"""
if deviceId is None:
deviceId = str(uuid.uuid4())
return self.s.post(
"{}/v1/login/register".format(self.root_url),
"{}/v1/login/register".format(self.root_url),
data={
'email': email,
'password': password,
@ -124,35 +125,35 @@ class AuthenticationAPI:
})
def disable_otp(self, totp):
'''
POST /v1/login/otp/deregistration
"""
POST /v1/login/otp/deregistration
params:
totp
response:
403: {"message": "Invalid OTP code provided, please try again"}
rate-limit: 5
auth: yes
'''
"""
return self.s.post(
"{}/v1/login/otp/deregistration".format(self.root_url),
"{}/v1/login/otp/deregistration".format(self.root_url),
data={
'totp': totp
})
def email_use_status(self, email):
'''
"""
GET /v1/login/{email}
response:
200: {"message": "HAS_PASSWORD"}
rate-limit: 5
auth: no
'''
"""
return self.s.get(
"{}/v1/login/{}".format(self.root_url, email)
)
def enroll_otp(self, totp, secret):
'''
"""
POST /v1/login/otp/registration
params:
totp
@ -161,32 +162,32 @@ class AuthenticationAPI:
200: {"message": "OK"}
rate-limit: 5
auth: yes
'''
"""
return self.s.post(
"{}/v1/login/otp/registration".format(self.root_url),
"{}/v1/login/otp/registration".format(self.root_url),
data={
'totp': totp,
'secret': secret
})
def get_a_captcha(self):
'''
"""
GET /v1/login/captcha
base64 png
response:
200: {"captchaToken": "00cd2762aeea4bc3ae93f504d739de88", "data": "/9j/2wBDAAY..."}
rate-limit: 6
auth: no
'''
"""
return self.s.get("{}/v1/login/captcha".format(self.root_url))
def logout(self, authenticationToken):
'''
POST /v1/logout
params:
"""
POST /v1/logout
params:
authenticationToken
auth: yes
'''
"""
return self.s.post(
"{}/v1/logout".format(self.root_url),
data={
@ -195,7 +196,7 @@ class AuthenticationAPI:
)
def request_password_reset(self, email):
'''
"""
POST /v1/login/resetReqeust
params:
email
@ -203,7 +204,7 @@ class AuthenticationAPI:
200: {"message": "OK"}
rate-limit: 3
auth: no
'''
"""
return self.s.post(
"{}/v1/login/resetRequest".format(self.root_url),
data={
@ -212,7 +213,7 @@ class AuthenticationAPI:
)
def request_signin_link_for_email(self, email, captchaToken, captchaValue, deviceId):
'''
"""
POST /v1/signin/request
removed
params:
@ -222,7 +223,7 @@ class AuthenticationAPI:
captchaValue
response:
404: {"message": "No resource for URL", "fieldvalidationsMap": []}}
'''
"""
if deviceId is None:
deviceId = str(uuid.uuid4())
@ -237,7 +238,7 @@ class AuthenticationAPI:
)
def reset_user_password(self, password, passwordConfirm, resetToken):
'''
"""
POST /v2/login/password/reset/submit
params:
password
@ -247,10 +248,10 @@ class AuthenticationAPI:
400: {"message": "Verification code expired", "fieldvalidationsMap": [] }
rate-limit: 4
auth: no
'''
"""
return self.s.post(
"{}/v2/login/password/reset/submit".format(self.root_url),
data = {
data={
'password': password,
'passwordConfirm': passwordConfirm,
'resetToken': resetToken
@ -258,7 +259,7 @@ class AuthenticationAPI:
)
def send_email_reminder(self, username):
'''
"""
POST /v1/login/reminder
sends email reminder for username
params:
@ -267,7 +268,7 @@ class AuthenticationAPI:
200: {"message": "success"}
rate-limit: 15
auth: no
'''
"""
return self.s.post(
"{}/v1/login/reminder".format(self.root_url),
data={
@ -276,7 +277,7 @@ class AuthenticationAPI:
)
def send_notification_token(self, notificationId):
'''
"""
POST /v1/notification
Mobile push notification token
params:
@ -285,16 +286,16 @@ class AuthenticationAPI:
200: {"message": "success"}
rate-limit: 5
auth: yes
'''
"""
return self.s.post(
"{}/v1/notification".format(self.root_url),
data = {
data={
'notificationId': notificationId
}
)
def sign_in_with_email(self, email, code, deviceId=None):
'''
"""
POST /v1/signin
sign in using code sent to email. removed
params:
@ -306,7 +307,7 @@ class AuthenticationAPI:
notificationId
response:
404: { "message": "No resource for URL", "fieldvalidationsMap": [] }
'''
"""
if deviceId is None:
deviceId = str(uuid.uuid4())
@ -320,8 +321,8 @@ class AuthenticationAPI:
)
def sign_up_email(self, email, name, deviceId=None):
'''
POST /v1/signup
"""
POST /v1/signup
removed
params:
email
@ -329,7 +330,7 @@ class AuthenticationAPI:
deviceId
response:
404: { "message": "No resource for URL", "fieldvalidationsMap": [] }
'''
"""
if deviceId is None:
deviceId = str(uuid.uuid4())
@ -343,7 +344,7 @@ class AuthenticationAPI:
)
def verify_reset_code(self, token):
'''
"""
POST /v2/login/password/reset/verify
params:
email (optional)
@ -353,11 +354,10 @@ class AuthenticationAPI:
200: {"valid": true}
rate-limit: 4
auth: no
'''
"""
return self.s.post(
"{}/v2/login/password/reset/verify".format(self.root_url),
data={
'token': token,
}
)

View File

@ -48,4 +48,4 @@ class V2AuthenticationAPI:
return self.s.post("{}/v2/login/sms/otp/submit".format(self.root_url), *args, **kwargs)
def submit_totp(self, *args, **kwargs):
return self.s.post("{}/v2/login/totp/submit".format(self.root_url), *args, **kwargs)
return self.s.post("{}/v2/login/totp/submit".format(self.root_url), *args, **kwargs)

View File

@ -1,4 +1,3 @@
class CampaignManagementAPI:
def __init__(self, session, root_url="http://api.parler.com"):
self.root_url = root_url
@ -23,4 +22,5 @@ class CampaignManagementAPI:
return self.s.post("{}/v3/promotionNetwork/campaign".format(self.root_url), *args, *kwargs)
def submit_campaign(self, identifier, *args, **kwargs):
return self.s.post("{}/v3/promotionNetwork/campaign/{}/submit".format(self.root_url, identifier), *args, *kwargs)
return self.s.post("{}/v3/promotionNetwork/campaign/{}/submit".format(self.root_url, identifier), *args,
*kwargs)

View File

@ -1,21 +1,26 @@
class CampaignManagementPromoterAPI:
def __init__(self, session, root_url="http://api.parler.com"):
self.root_url = root_url
self.s = session
def add_promoter_for_request(self, identifier, *args, **kwargs):
return self.s.post("{}/v3/promotionNetwork/campaign/{}/promoter".format(self.root_url, identifier), *args, **kwargs)
return self.s.post("{}/v3/promotionNetwork/campaign/{}/promoter".format(self.root_url, identifier), *args,
**kwargs)
def get_details_for_promoter(self, campaignId, promoterId, *args, **kwargs):
return self.s.get("{}/v3/promotionNetwork/campaign/{}/promoter/{}".format(self.root_url, campaignId, promoterId), *args, **kwargs)
return self.s.get(
"{}/v3/promotionNetwork/campaign/{}/promoter/{}".format(self.root_url, campaignId, promoterId), *args,
**kwargs)
def get_current_list_of_promoters_for_campaign(self, campaignId, *args, **kwargs):
return self.s.get("{}/v3/promotionNetwork/campaign/{}/promoters".format(self.root_url, campaignId), *args, **kwargs)
return self.s.get("{}/v3/promotionNetwork/campaign/{}/promoters".format(self.root_url, campaignId), *args,
**kwargs)
def get_list_of_possible_promoters_for_campaign(self, campaignId, *args, **kwargs):
return self.s.get("{}/v3/promotionNetwork/campaign/{}/promoters/new".format(self.root_url, campaignId), *args, **kwargs)
return self.s.get("{}/v3/promotionNetwork/campaign/{}/promoters/new".format(self.root_url, campaignId), *args,
**kwargs)
def remove_promoter_from_campaign(self, campaignId, promoterId, *args, **kwargs):
return self.s.delete("{}/v3/promotionNetwork/campaign/{}/promoter/{}".format(self.root_url, campaignId, promoterId), *args, **kwargs)
return self.s.delete(
"{}/v3/promotionNetwork/campaign/{}/promoter/{}".format(self.root_url, campaignId, promoterId), *args,
**kwargs)

View File

@ -1,4 +1,3 @@
class CommentsAPI:
def __init__(self, session, root_url="http://api.parler.com"):
self.root_url = root_url
@ -10,7 +9,7 @@ class CommentsAPI:
# id
def delete_comment(self, _id, *args, **kwargs):
return self.s.delete("{}/v1/comment".format(self.root_url), params={'id': _id} *args, **kwargs)
return self.s.delete("{}/v1/comment".format(self.root_url), params={'id': _id} * args, **kwargs)
# id, up
def downvote_comment(self, *args, **kwargs):

View File

@ -1,4 +1,3 @@
class ContactsUploaderAPI:
def __init__(self, session, root_url="http://api.parler.com"):
self.root_url = root_url
@ -14,5 +13,6 @@ class ContactsUploaderAPI:
}]
}
'''
def start_uploading(self, *args, **kwargs):
return self.s.post("{}/v2/contacts".format(self.root_url), *args, **kwargs)
return self.s.post("{}/v2/contacts".format(self.root_url), *args, **kwargs)

View File

@ -4,4 +4,4 @@ class ContentModerationAPI:
self.s = session
def get_reported_content(self, *args, **kwargs):
return self.s.get("{}/v2/contentModeration/reports".format(self.root_url), *args, **kwargs)
return self.s.get("{}/v2/contentModeration/reports".format(self.root_url), *args, **kwargs)

View File

@ -1,11 +1,10 @@
class ConversionAPI:
def __init__(self, session, root_url="http://api.parler.com"):
self.root_url = root_url
self.s = session
def convert(self, _type, uuid):
'''
"""
GET /v3/idConversion/{type}/{uuid}
params:
type: one of (user, post, comment, image, video, link)
@ -14,13 +13,13 @@ class ConversionAPI:
hidden sequential ID, as protobuf varint
rate-limit: none
auth: yes
'''
"""
return self.s.get(
"{}/v3/idConversion/{}/{}".format(self.root_url, _type, uuid)
)
def reverse_convert(self, _type, _id):
'''
"""
GET /v3/uuidConversion/{type}/{id}
(*) this is enumerable
params:
@ -30,7 +29,7 @@ class ConversionAPI:
public-facing UUID of the entity
rate-limit: none
auth: yes
'''
"""
return self.s.get(
"{}/v3/uuidConversion/{}/{}".format(self.root_url, _type, _id)
)
)

View File

@ -6,4 +6,3 @@ class FlagsAPI:
def get_flags_for(self, userUuid, *args, **kwargs):
# i have no idea what this is
return self.s.get("{}/v3/flags/user/uuid/{}".format(self.root_url, userUuid), *args, **kwargs)

View File

@ -51,7 +51,7 @@ class ModerationAPI:
# organization, startkey
def get_pending_comments(self, *args, **kwargs):
return self.s.get("{}/v1/moderation/pending".format(self.root_url), *args, **kwargs)
# organization, startkey
def get_spam_comments(self, *args, **kwargs):
return self.s.get("{}/v1/moderation/spam".format(self.root_url), *args, **kwargs)
@ -89,9 +89,9 @@ class ModerationAPI:
def post_iaa_report(self, *args, **kwargs):
return self.s.post("{}/v2/iaa/moderation/report".format(self.root_url), *args, **kwargs)
# words, action, organization
# words, action, organization
def delete_word_filter(self, *args, **kwargs):
return self.s.post("{}/v1/moderation/filter/word/delete".format(self.root_url), *args, **kwargs)
def set_nsfw_enabled(self, val, *args, **kwargs):
return self.s.post("{}/v2/profile/toggle/noSensitive/{}".format(self.root_url, val), *args, **kwargs)
return self.s.post("{}/v2/profile/toggle/noSensitive/{}".format(self.root_url, val), *args, **kwargs)

View File

@ -33,12 +33,14 @@ from parler.wallet_general import WalletGeneralAPI
from parler.wallet import WalletAPI
import requests
class Parler:
'''
the api is accessible at api.parler.com and par.pw.
staging api = api.speak-free.com
mst and jst cookie are same as on web
'''
def __init__(self, mst=None, jst=None, root_url="https://api.parler.com"):
session = requests.Session()
session.headers['User-Agent'] = 'Parler%20Staging/545 CFNetwork/978.0.7 Darwin 18.7.0'

View File

@ -4,4 +4,4 @@ class ParlerDataAPI:
self.s = session
def upload_data(self, *args, **kwargs):
return self.s.post("{}/v2/upload/image".format(self.root_url), *args, **kwargs)
return self.s.post("{}/v2/upload/image".format(self.root_url), *args, **kwargs)

View File

@ -15,7 +15,6 @@ class PostsAPI:
def get_posts_using_urls(self, *args, **kwargs):
return self.s.post("{}/v1/wordpress/posts".format(self.root_url), *args, **kwargs)
def get_post_impressions_over_time(self, post, *args, **kwargs):
return self.s.get("{}/v1/post/{}/impressions/time".format(self.root_url, post), *args, **kwargs)

View File

@ -4,13 +4,15 @@ class PromoterCampaignManagementAPI:
self.s = session
def approve_promoter_campaign(self, campaign, *args, **kwargs):
return self.s.post("{}/v3/promotionNetwork/promoter/campaign/{}".format(self.root_url, campaign), *args, **kwargs)
return self.s.post("{}/v3/promotionNetwork/promoter/campaign/{}".format(self.root_url, campaign), *args,
**kwargs)
def get_current_status_of_promotion(self, *args, **kwargs):
return self.s.get("{}/v3/promotionNetwork/promoter".format(self.root_url), *args, **kwargs)
def get_details_for_campaign(self, campaign, *args, **kwargs):
return self.s.get("{}/v3/promotionNetwork/promoter/campaign/{}".format(self.root_url, campaign), *args, **kwargs)
return self.s.get("{}/v3/promotionNetwork/promoter/campaign/{}".format(self.root_url, campaign), *args,
**kwargs)
def get_list_of_campaigns(self, *args, **kwargs):
return self.s.get("{}/v3/promotionNetwork/promoter/campaigns".format(self.root_url), *args, **kwargs)
@ -22,4 +24,4 @@ class PromoterCampaignManagementAPI:
return self.s.post("{}/v3/promotionNetwork/promoter/cpm".format(self.root_url), *args, **kwargs)
def set_promoter_guidelines(self, *args, **kwargs):
return self.s.post("{}/v3/promotionNetwork/promoter/guidelines".format(self.root_url), *args, **kwargs)
return self.s.post("{}/v3/promotionNetwork/promoter/guidelines".format(self.root_url), *args, **kwargs)

View File

@ -84,4 +84,4 @@ class UserAPI:
# id, userId, username
def unmute_user(self, *args, **kwargs):
return self.s.delete("{}/v1/user/mute".format(self.root_url), *args, **kwargs)
return self.s.delete("{}/v1/user/mute".format(self.root_url), *args, **kwargs)

View File

@ -4,4 +4,4 @@ class WalletAPI:
self.s = session
def get_billing_information(self, *args, **kwargs):
return self.s.get("{}/v3/billing".format(self.root_url), *args, **kwargs)
return self.s.get("{}/v3/billing".format(self.root_url), *args, **kwargs)

13
setup.py Normal file
View File

@ -0,0 +1,13 @@
from setuptools import setup
setup(
name="parler-api",
version="1.0",
description="Reverse engineered Parler API",
author="d0nk",
author_email="",
packages=["parler_api"],
install_requires=[
"requests",
]
)