Merge pull request #4 from bellingcat/dev-1

Dev 1
This commit is contained in:
Richard Mwewa
2023-10-12 14:10:25 +02:00
committed by GitHub
9 changed files with 115 additions and 49 deletions

View File

@@ -11,42 +11,41 @@ pip install facebook-downloader
``` ```
### Note ### Note
> You will need to have the FireFox browser installed on your pc (for the PyPI Package) > You will need to have the FireFox browser installed on your pc.
>> The program is dependent on selenium, so in order to run it, you will have to download and properly setup geckodriver (setup instructions available below)
# Docker # Docker
## Pull the image ## Build the container
``` ```
docker pull rly0nheart/facebook-downloader:facebook-downloader docker build -t my-facebook-downloader .
``` ```
# Geckodriver setup # Geckodriver setup
> This assumes you've cloned the repository with `git clone https://github.com/bellingcat/facebook-downloader`
## Linux ## Linux
**1. Go to the geckodriver [releases page](https://github.com/mozilla/geckodriver/releases/). Find the latest version of the driver for your platform and download it** **1.** Navigate to the facebook-downloader directory
**2. Extract the downloaded file**
``` ```
tar -xvzf geckodriver* cd facebook-downloader
```
**3. Add geckodriver to your system path**
```
export PATH=$PATH:/path/to/downloaded/geckodriver
``` ```
### Note **2.** Find the `install.sh` script and run it
> If you encounter issues with the above commands, then you should run them as root ```
./install.sh
```
> This assumes the script was already made executable with the `chmod +x uninstall.sh` command.
## Windows ## Windows
**1. Go to the geckodriver [releases page](https://github.com/mozilla/geckodriver/releases/). Find the geckodriver.exe binary for your platform and download it** **1.** Navigate to the facebook-downloader directory
```
**2. Move the downloaded executable to** *C:\Users\yourusername\AppData\Local\Programs\Python\Python310* cd facebook-downloader
```
### Note
> The numbers on the directory 'Python310' will depend on the version of Python you have
## Mac OS
* [Set up Selenium & GeckoDriver (Mac)](https://medium.com/dropout-analytics/selenium-and-geckodriver-on-mac-b411dbfe61bc)
**2.** Find the `install.ps1` script and run it
```
.\install.ps1
```
> The installation scripts will download and setup geckodriver, then install **facebook-downloader**.
# Usage # Usage
``` ```
@@ -55,10 +54,8 @@ facebook_downloader <video-url>
# Docker # Docker
``` ```
docker run -it -v $PWD/downloads:/app/downloads facebook-downloader <facebook_url> docker run --tty --volume $PWD/downloads:/app/downloads my-facebook-downloader <facebook_video_url>
``` ```
## Note
> The url format should be as follows; https://www.facebook.com/PageName/videos/VideoID
# Optional Arguments # Optional Arguments
@@ -70,6 +67,6 @@ facebook_downloader <video-url>
# Donations # Donations
If you would like to donate, you could Buy A Coffee for the developer using the button below If you would like to donate, you could Buy A Coffee for the developer using the button below
<a href="https://www.buymeacoffee.com/189381184" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Coffee" height="41" width="174"></a> <a href="https://www.buymeacoffee.com/_rly0nheart"><img src="https://img.buymeacoffee.com/button-api/?text=Buy me a coffee&emoji=&slug=_rly0nheart&button_colour=40DCA5&font_colour=ffffff&font_family=Comic&outline_colour=000000&coffee_colour=FFDD00" /></a>
Your support will be much appreciated! Your support will be much appreciated!

View File

@@ -0,0 +1,2 @@
__author__ = "Richard Mwewa"
__version__ = "1.4.0"

View File

@@ -8,10 +8,11 @@ from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions from selenium.webdriver.support import expected_conditions
from . import __version__, __author__
class FacebookDownloader: class FacebookDownloader:
def __init__(self): def __init__(self):
self.__program_version_number = "1.4.0"
self.__base_url = "https://getfvid.com" self.__base_url = "https://getfvid.com"
self.__update_check_endpoint = "https://api.github.com/repos/rly0nheart/facebook-downloader/releases/latest" self.__update_check_endpoint = "https://api.github.com/repos/rly0nheart/facebook-downloader/releases/latest"
self.__home_directory = os.path.expanduser("~") self.__home_directory = os.path.expanduser("~")
@@ -21,12 +22,12 @@ class FacebookDownloader:
__option.add_argument('--headless') __option.add_argument('--headless')
self.__driver = webdriver.Firefox(options=__option) self.__driver = webdriver.Firefox(options=__option)
parser = argparse.ArgumentParser(description='facebook-downloader — by Richard Mwewa', parser = argparse.ArgumentParser(description=f'facebook-downloader — by {__author__}',
epilog='Facebook video downloader.') epilog='Facebook video downloader.')
parser.add_argument('url', help='facebook video url') parser.add_argument('url', help='facebook video url')
parser.add_argument('-a', '--audio', help='download file as audio', action='store_true') parser.add_argument('-a', '--audio', help='download file as audio', action='store_true')
parser.add_argument('-o', '--output', help='output filename', default="") parser.add_argument('-o', '--output', help='output filename', default="")
parser.add_argument('-v', '--version', action='version', version=self.__program_version_number) parser.add_argument('-v', '--version', action='version', version=__version__)
self.__args = parser.parse_args() self.__args = parser.parse_args()
@staticmethod @staticmethod
@@ -55,36 +56,34 @@ class FacebookDownloader:
:rtype: str :rtype: str
""" """
return f""" return f"""
facebook-downloader v{self.__program_version_number} Copyright (C) 2023 Richard Mwewa facebook-downloader v{__version__} Copyright (C) 2022-2023 Richard Mwewa
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your option) any later version. the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
""" """
def check_updates(self) -> None: def check_updates(self):
""" """
Checks if the program's version tag matches the tag of the latest release on GitHub. Checks if the program's version tag matches the tag of the latest release on GitHub.
If the tags match, assume the program is up-to-date. If the tags match, assume the program is up-to-date.
:return: None
""" """
with requests.get(self.__update_check_endpoint) as response: with requests.get(self.__update_check_endpoint) as response:
if response.json()['tag_name'] != self.__program_version_number: remote_version = response.json().get('tag_name')
print(f"* A new release is available -> facebook-downloader v{response.json()['tag_name']}.\n" if remote_version != __version__:
print(f"* A new release is available -> facebook-downloader v{remote_version}.\n"
f"* Run 'pip install --upgrade facebook-downloader' to get the updates.\n") f"* Run 'pip install --upgrade facebook-downloader' to get the updates.\n")
else:
pass
def __get_download_type_element(self) -> str: def __get_download_type_element(self) -> str:
""" """
Gets the web element according to the specified command-line arguments. Gets the web element according to the specified command-line arguments.
HD: /html/body/div[2]/div/div/div[1]/div/div[2]/div/div[3]/p[1]/a ELements
--------
SD: /html/body/div[2]/div/div/div[1]/div/div[2]/div/div[3]/p[2]/a - HD: /html/body/div[2]/div/div/div[1]/div/div[2]/div/div[3]/p[1]/a
- SD: /html/body/div[2]/div/div/div[1]/div/div[2]/div/div[3]/p[2]/a
Audio: /html/body/div[2]/div/div/div[1]/div/div[2]/div/div[3]/p[3]/a - Audio: /html/body/div[2]/div/div/div[1]/div/div[2]/div/div[3]/p[3]/a
:return: Web element :return: Web element
""" """
@@ -102,13 +101,11 @@ class FacebookDownloader:
:return: None :return: None
""" """
# Construct and create the directory if it doesn't already exist # Construct and create the directory if it doesn't already exist
os.makedirs(os.path.join(self.__home_directory, "facebook-videos"), exist_ok=True) os.makedirs(os.path.join(self.__home_directory, "facebook-downloader"), exist_ok=True)
def download_video(self): def download_video(self):
""" """
Opens https://getfvid.com with selenium and uses the specified facebook video link as a query. Opens https://getfvid.com with selenium and uses the specified facebook video link as a query.
:return:
""" """
# Open the base url. # Open the base url.
self.__driver.get(self.__base_url) self.__driver.get(self.__base_url)

View File

@@ -1,7 +1,7 @@
from facebook_downloader.downloader import FacebookDownloader from facebook_downloader.downloader import FacebookDownloader
def run(): def start_downloader():
try: try:
# Initialise the FaceBookDownloader instance. # Initialise the FaceBookDownloader instance.
program = FacebookDownloader() program = FacebookDownloader()

27
install.ps1 Normal file
View File

@@ -0,0 +1,27 @@
# Define URL for GeckoDriver
$geckoURL = "https://github.com/mozilla/geckodriver/releases/download/v0.33.0/geckodriver-v0.33.0-win64.zip"
# Define target directories for installation
$geckoDir = "$env:USERPROFILE\facebook-downloader\GeckoDriver"
# Function to download a file
function DownloadFile([string]$url, [string]$path) {
Invoke-WebRequest -Uri $url -OutFile $path
}
# Check if GeckoDriver directory exists, if not create and download
if (-Not (Test-Path $geckoDir)) {
New-Item -Path $geckoDir -ItemType Directory
Write-Host "Downloading GeckoDriver..."
DownloadFile $geckoURL "$geckoDir\geckodriver.zip"
# Unzipping the GeckoDriver
Expand-Archive -Path "$geckoDir\geckodriver.zip" -DestinationPath $geckoDir
Remove-Item "$geckoDir\geckodriver.zip"
}
# Add the geckodriver directory to PATH
[Environment]::SetEnvironmentVariable("PATH", [Environment]::GetEnvironmentVariable("PATH", [EnvironmentVariableTarget]::User) + ";$geckoDir", [EnvironmentVariableTarget]::User)
pip install .
Write-Host "Setup complete."

9
install.sh Normal file
View File

@@ -0,0 +1,9 @@
#!/bin/bash
# Download geckodriver .tar.gz file and pipe it to 'tar' to extract the geckodriver binary directly into /usr/bin.
curl -L https://github.com/mozilla/geckodriver/releases/download/v0.33.0/geckodriver-v0.33.0-linux64.tar.gz | \
tar xz -C /usr/bin
# Install Python packages defined in the current directory's setup.py/pyproject.toml file. (pyproject.toml in this case)
pip3 install .
echo "Setup complete."

View File

@@ -25,9 +25,9 @@ classifiers = [
packages = ["facebook_downloader"] packages = ["facebook_downloader"]
[project.urls] [project.urls]
homepage = "https://www.bellingcat.com" homepage = "https://pypi.org/project/facebook-downloader"
documentation = "https://github.com/bellingcat/facebook-downloader/wiki" documentation = "https://github.com/bellingcat/facebook-downloader/wiki"
repository = "https://github.com/bellingcat/facebook-downloader" repository = "https://github.com/bellingcat/facebook-downloader"
[project.scripts] [project.scripts]
facebook_downloader = "facebook_downloader.main:run" facebook_downloader = "facebook_downloader.main:start_downloader"

26
uninstall.ps1 Normal file
View File

@@ -0,0 +1,26 @@
# Define target directory for removal
$geckoDir = "$env:USERPROFILE\facebook-downloader\GeckoDriver"
# Function to remove directory
function RemoveDir([string]$dirPath) {
if (Test-Path $dirPath) {
Remove-Item -Path $dirPath -Recurse -Force
Write-Host "Removed directory: $dirPath"
} else {
Write-Host "Directory $dirPath does not exist."
}
}
# Remove GeckoDriver directory
RemoveDir $geckoDir
# Remove the geckodriver directory from PATH
$pathEnv = [Environment]::GetEnvironmentVariable("PATH", [EnvironmentVariableTarget]::User)
$newPath = ($pathEnv -split ";" | Where-Object { $_ -ne $geckoDir }) -join ";"
[Environment]::SetEnvironmentVariable("PATH", $newPath, [EnvironmentVariableTarget]::User)
Write-Host "Removed GeckoDriver directory from PATH."
# Uninstall facebook-downloader Python package
pip uninstall facebook-downloader -y
Write-Host "Cleanup complete."

8
uninstall.sh Normal file
View File

@@ -0,0 +1,8 @@
#!/bin/bash
# Remove the geckodriver binary from /usr/bin
sudo rm /usr/bin/geckodriver -v
# Uninstall tor2tor
pip3 uninstall facebook-downloader -y -v
echo "Cleanup complete."