Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added some features and using a seperate condiguration file. #117

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
configurations.py
logs/
.vscode/
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Content will be named as DATE_ID.EXT (e.g. 2021-04-17_123456.jpg)

#### Requires
Requires Python3 and 'requests': `python -m pip install requests`
or
Using pip directly: `pip -r install requirements.txt`

## Features
* Choose what type of content to download (photos, videos, posts, stories, messages, purchases, archived)
Expand All @@ -21,7 +23,7 @@ Requires Python3 and 'requests': `python -m pip install requests`
First make sure to set your session variables in the script and configure your options.

`./onlyfans-dl.py <profiles / all> <max age (optional)>`
* `<profiles>` - the usernames of profiles to download. Use "all" to get all currently subscribed profiles
* `<profiles>` - the usernames of profiles to download. Use "all" to get all currently subscribed profiles. With "all_subs" even inactive subs and there chats getting pulled.
* `<max age>` - Optional: Only get posts from the last &lt;integer&gt; days (Messages/Paid not affected)
* `max age = 0` - sets max age to latest date from the filenames for each profile individually

Expand All @@ -40,7 +42,7 @@ You need your browser's __user-agent__, onlyfans **sess**ion cookie, __x-bc__ HT
- Click __Headers__ sub-tab (default)
- Click on one of the JSON elements (may need to refresh page) and look under __request headers__ on the right

There are variables for each of these values at the top of the script. Make sure to update them every time you login or your browser updates.
Those settings need to be set in the configuration.py. Duplicate configuration-example.py and set the variables accordingly.

#### ToDo
A post with a single photo and video shouldn't be considered an album.\
Expand Down
41 changes: 41 additions & 0 deletions configurations-example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
######################
# CONFIGURATIONS #
######################

#Session Variables (update every time you login or your browser updates)
# USER_ID aka auth_id coockie
USER_ID = ""
USER_AGENT = ""
# X_BC aka fp
X_BC = ""
SESS_COOKIE = ""

#0 = do not print file names or api calls
#1 = print filenames only when max_age is set
#2 = always print filenames
#3 = print api calls
#4 = print skipped files that already exist
VERBOSITY = 2
#Download Directory. Uses CWD if null
DL_DIR = ''
#List of accounts to skip
ByPass = ['']

#Separate photos into subdirectories by post/album (Single photo posts are not put into subdirectories)
ALBUMS = True
#Use content type subfolders (messgaes/archived/stories/purchased), or download everything to /profile/photos and /profile/videos
USE_SUB_FOLDERS = True

#Content types to download
VIDEOS = True
PHOTOS = True
AUDIO = True
POSTS = True
STORIES = True
MESSAGES = True
ARCHIVED = True
PURCHASED = True

######################
# END CONFIGURATIONS #
######################
120 changes: 48 additions & 72 deletions onlyfans-dl.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,46 +10,7 @@
from datetime import datetime, timedelta
requests.urllib3.disable_warnings()

######################
# CONFIGURATIONS #
######################

#Session Variables (update every time you login or your browser updates)
USER_ID = ""
USER_AGENT = ""
X_BC = ""
SESS_COOKIE = ""

#0 = do not print file names or api calls
#1 = print filenames only when max_age is set
#2 = always print filenames
#3 = print api calls
#4 = print skipped files that already exist
VERBOSITY = 2
#Download Directory. Uses CWD if null
DL_DIR = ''
#List of accounts to skip
ByPass = ['']

#Separate photos into subdirectories by post/album (Single photo posts are not put into subdirectories)
ALBUMS = True
#Use content type subfolders (messgaes/archived/stories/purchased), or download everything to /profile/photos and /profile/videos
USE_SUB_FOLDERS = True

#Content types to download
VIDEOS = True
PHOTOS = True
AUDIO = True
POSTS = True
STORIES = True
MESSAGES = True
ARCHIVED = True
PURCHASED = True

######################
# END CONFIGURATIONS #
######################

from configurations import *

API_URL = "https://onlyfans.com/api2/v2"
new_files = 0
Expand Down Expand Up @@ -94,7 +55,7 @@ def showAge(myStr):


def latest(profile):
latest = "0";
latest = "0"
for dirpath, dirs, files in os.walk(profile):
for f in files:
if f.startswith('20'):
Expand All @@ -110,6 +71,8 @@ def api_request(endpoint, apiType):
getParams['order'] = "desc"
if apiType == 'subscriptions':
getParams['type'] = 'active'
if apiType == 'all_subscriptions':
getParams['type'] = 'all'
if MAX_AGE and apiType != 'messages' and apiType != 'purchased' and apiType != 'subscriptions': #Cannot be limited by age
getParams['afterPublishTime'] = str(MAX_AGE) + ".000000"
age = " age " + str(showAge(getParams['afterPublishTime']))
Expand Down Expand Up @@ -168,6 +131,12 @@ def get_subscriptions():
return
return [row['username'] for row in subs]

def get_all_subscriptions():
subs = api_request("/subscriptions/subscribes", "all_subscriptions")
if "error" in subs:
print("\nSUBSCRIPTIONS ERROR: " + subs["error"]["message"])
return
return [row['username'] for row in subs]

def download_media(media, subtype, postdate, album = ''):
filename = postdate + "_" + str(media["id"])
Expand Down Expand Up @@ -225,7 +194,7 @@ def download_media(media, subtype, postdate, album = ''):


def get_content(MEDIATYPE, API_LOCATION):
posts = api_request(API_LOCATION, MEDIATYPE)
posts = api_request(apiType=MEDIATYPE, endpoint=API_LOCATION)
if "error" in posts:
print("\nERROR: " + API_LOCATION + " :: " + posts["error"]["message"])
if MEDIATYPE == "messages":
Expand Down Expand Up @@ -284,37 +253,44 @@ def get_content(MEDIATYPE, API_LOCATION):
if PROFILE_LIST[0] == "all":
PROFILE_LIST = get_subscriptions()

for PROFILE in PROFILE_LIST:
if PROFILE in ByPass:
if VERBOSITY > 0:
print("skipping " + PROFILE)
continue
user_info = get_user_info(PROFILE)
if PROFILE_LIST[0] == "all_subs":
PROFILE_LIST = get_all_subscriptions()

if "id" in user_info:
PROFILE_ID = str(user_info["id"])
else:
continue
if not len(PROFILE_LIST) < 1:
for PROFILE in PROFILE_LIST:
if PROFILE in ByPass:
if VERBOSITY > 0:
print("skipping " + PROFILE)
continue
user_info = get_user_info(PROFILE)

if LATEST:
latestDate = latest(PROFILE)
if latestDate != "0":
MAX_AGE = int(datetime.strptime(latestDate + ' 00:00:00', '%Y-%m-%d %H:%M:%S').timestamp())
print("\nGetting posts newer than " + latestDate + " 00:00:00 UTC")
if "id" in user_info:
PROFILE_ID = str(user_info["id"])
else:
continue

if os.path.isdir(PROFILE):
print("\n" + PROFILE + " exists.\nDownloading new media, skipping pre-existing.")
else:
print("\nDownloading content to " + PROFILE)

if POSTS:
get_content("posts", "/users/" + PROFILE_ID + "/posts")
if ARCHIVED:
get_content("archived", "/users/" + PROFILE_ID + "/posts/archived")
if STORIES:
get_content("stories", "/users/" + PROFILE_ID + "/stories")
if MESSAGES:
get_content("messages", "/chats/" + PROFILE_ID + "/messages")
if PURCHASED:
get_content("purchased", "/posts/paid")
if LATEST:
latestDate = latest(PROFILE)
if latestDate != "0":
MAX_AGE = int(datetime.strptime(latestDate + ' 00:00:00', '%Y-%m-%d %H:%M:%S').timestamp())
print("\nGetting posts newer than " + latestDate + " 00:00:00 UTC")

if os.path.isdir(PROFILE):
print("\n" + PROFILE + " exists.\nDownloading new media, skipping pre-existing.")
else:
print("\nDownloading content to " + PROFILE)

if POSTS:
get_content("posts", "/users/" + PROFILE_ID + "/posts")
if ARCHIVED:
get_content("archived", "/users/" + PROFILE_ID + "/posts/archived")
if STORIES:
get_content("stories", "/users/" + PROFILE_ID + "/stories")
if MESSAGES:
get_content("messages", "/chats/" + PROFILE_ID + "/messages")
if PURCHASED:
get_content("purchased", "/posts/paid")

else:
print("No Profile found!")

1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
requests