Skip to content

Commit

Permalink
test: preview
Browse files Browse the repository at this point in the history
  • Loading branch information
qx6ghqkz committed Dec 30, 2024
1 parent a04e97e commit 7108b3c
Show file tree
Hide file tree
Showing 8 changed files with 1,297 additions and 553 deletions.
6 changes: 6 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Visual Studio
.vscode/

# Python
__pycache__/

# Scripts
scripts/
*.bat
Expand Down Expand Up @@ -28,3 +31,6 @@ Dockerfile
LICENSE
README.md
SECURITY.md

# Misc
drafts/
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
# Python
__pycache__/

# Scripts
scripts/
*.bat
*.cmd
*.ps1

# Environments
env/
venv/
.env
.venv

# Misc
drafts/
19 changes: 14 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,13 @@ services:
restart: on-failure
```
**Important**: Make sure you mount the directory containing the config file rather than the file itself. This ensures changes to the config file are propagated to the running Docker container and you will not need to restart the container. More information on this issue [here](https://github.com/moby/moby/issues/15793#issuecomment-135411504).
#### Important Notes
You can use the environment variables `UID` and `GID` to change the user ID and group ID of the user running the server process. This is important because downloaded files will be owned by this user. Make sure the IDs match those of the user on your host system. The default `UID:GID` is `1000:1000` when left unspecified.
- Make sure you mount the directory containing the config file rather than the file itself. This ensures changes to the config file are propagated to the running Docker container and you will not need to restart the container. More information on this issue [here](https://github.com/moby/moby/issues/15793#issuecomment-135411504).
- The output download directory depends on the `base-directory` in your gallery-dl config file. Make sure it is the absolute path `/gallery-dl/` instead of the relative path `./gallery-dl/` or you will need to mount to `/usr/src/app/gallery-dl` instead (not recommended).

- You can use the environment variables `UID` and `GID` to change the user ID and group ID of the user running the server process. This is important because downloaded files will be owned by that user. Make sure the IDs match those of the user on your host system. The default `UID:GID` is `1000:1000` when left unspecified.

### Python

Expand Down Expand Up @@ -106,13 +110,18 @@ Configuration of gallery-dl is as documented in the [official documentation](htt

The configuration file must be mounted inside the Docker container in one of the locations where gallery-dl will check for the config file.

The server uses a custom target config location of `/config/gallery-dl.conf`. A [default configuration file](https://github.com/qx6ghqkz/gallery-dl-server/blob/main/gallery-dl.conf) for use with gallery-dl-server has been provided and will automatically be placed in the directory mounted to `/config` if the file does not already exist in that location.
### Locations

- `/config/gallery-dl.conf`
- `/config/config.json`

A [default configuration file](https://github.com/qx6ghqkz/gallery-dl-server/blob/main/gallery-dl.conf) for use with gallery-dl-server has been provided and will automatically be placed in the directory mounted to `/config` if the file does not already exist in that location.

For more information on configuration file options, see [gallery-dl/docs/configuration.rst](https://github.com/mikf/gallery-dl/blob/master/docs/configuration.rst).

Any additional directories specified in the configuration file must also be mounted inside the Docker container, for example if you specify a cookies file location then make sure that location is accessible from within the Docker container.
Any additional locations specified in the configuration file must also exist inside the Docker container. For example, if you specify a cookies file location, make sure that location is accessible from within the Docker container.

It is recommended you place any additional files such as archive, cache and cookies files inside the same `config` directory as `gallery-dl.conf` and then mount that directory to `/config` inside the container, as in the examples.
It is recommended you place any additional files such as archive, cache and cookies files inside the same directory mounted to `/config` along with the config file.

## Usage

Expand Down
142 changes: 142 additions & 0 deletions config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import logging

from collections.abc import MutableMapping

from output import stdout_write

from gallery_dl import config


_config = config._config
_files = config._files


def clear():
config.clear()


def load(_configs):
exit_code = None
loads = 0

if config.log.level <= logging.ERROR:
config.log.setLevel(logging.CRITICAL)

for path in _configs:
try:
config.load([path], strict=True)
except SystemExit as e:
if not exit_code:
exit_code = e.code
else:
loads += 1

if loads > 0:
stdout_write(f"Loaded gallery-dl configuration file(s): {_files}")
elif exit_code:
stdout_write(f"Unable to load configuration file. Exit code: {exit_code}")

if exit_code == 1:
stdout_write(f"Valid configuration file locations: {_configs}")


def add(dict=None, conf=_config, fixed=False, **kwargs):
if dict:
for k, v in dict.items():
if isinstance(v, MutableMapping):
if k in conf.keys() or not fixed:
conf[k] = add(v, conf.get(k) or {}, fixed=fixed)[0]
elif isinstance(v, list):
if k in conf.keys() or not fixed:
for i in v:
if not isinstance(i, MutableMapping):
if i not in conf.get(k, []) or not str(i).startswith("-"):
conf[k] = conf.get(k, []) + [i]
else:
if i not in conf.get(k, []):
conf[k] = conf.get(k, []) + [i]
else:
if k in conf.keys() or not fixed:
conf[k] = v

while isinstance(d := list(dict.values())[0], MutableMapping):
dict = d

if kwargs:
for key, val in kwargs.items():
for k, v in conf.items():
if isinstance(v, MutableMapping):
conf[k] = add(conf=v, fixed=fixed, **{key: val})[0]
else:
if k == key and key in conf.keys():
conf[k] = val
if dict:
return (conf, [dict, kwargs])
else:
return (conf, [kwargs])

return (conf, [dict])


def remove(path, item=None, key=None, value=None):
entries = []
removed = []

if isinstance(path, list):
_list = path

for entry in _list:
if item:
if entry == item:
if value:
try:
entry_index = _list.index(entry)
entry_next = _list[entry_index + 1]
except IndexError:
if "any" == value:
entries.append(entry)
else:
if "any" == value:
entries.extend((entry, entry_next))
elif entry_next == value:
entries.extend((entry, entry_next))
else:
entries.append(entry)
elif key:
if value:
if entry.get(key) == value:
entries.append(entry)
else:
if entry.get(key):
entries.append(entry)

for entry in entries:
try:
_list.remove(entry)
except Exception as e:
stdout_write(f"Exception: {e}")
else:
removed.append(entry)

if isinstance(path, dict):
_dict = path

if key:
if value:
for k, v in _dict.items():
if k == key and v == value:
entries.append(k)
else:
for k in _dict.keys():
if k == key:
entries.append(k)

for entry in entries:
try:
val = _dict.pop(entry)
except Exception as e:
stdout_write(f"Exception: {e}")
else:
removed.append({entry: val})

return removed
137 changes: 137 additions & 0 deletions download.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import sys
import ast

import config
import output

from gallery_dl import job


def run(url, request_options):
config.clear()

config_files = [
"/config/gallery-dl.conf",
"/config/config.json",
]

config.load(config_files)

output.setup_logging()

output.stdout_write(
f"Requesting download with the following overriding options: {request_options}"
)

entries = config_update(request_options)

if any(entries[0]):
output.stdout_write(f"Added entries to the config dict: {entries[0]}")

if any(entries[1]):
output.stdout_write(f"Removed entries from the config dict: {entries[1]}")

status = job.DownloadJob(url).run()

return status


def config_update(request_options):
entries_added = []
entries_removed = []

requested_format = request_options.get("video-options", "none-selected")

if requested_format == "download-video":
try:
cmdline_args = (
config._config.get("extractor", {})
.get("ytdl", {})
.get("cmdline-args", [])
)
except AttributeError:
pass
else:
entries_removed.extend(
config.remove(cmdline_args, item="--extract-audio")
+ config.remove(cmdline_args, item="-x")
)

try:
raw_options = (
config._config.get("extractor", {})
.get("ytdl", {})
.get("raw-options", {})
)
except AttributeError:
pass
else:
entries_removed.extend(
config.remove(raw_options, key="writethumbnail", value=False)
)

try:
postprocessors = (
config._config.get("extractor", {})
.get("ytdl", {})
.get("raw-options", {})
.get("postprocessors", [])
)
except AttributeError:
pass
else:
entries_removed.extend(
config.remove(postprocessors, key="key", value="FFmpegExtractAudio")
)

if requested_format == "extract-audio":
entries_added.extend(
config.add(
{
"extractor": {
"ytdl": {
"cmdline-args": [
"--extract-audio",
]
}
}
}
)[1]
+ config.add(
{
"extractor": {
"ytdl": {
"raw-options": {
"writethumbnail": False,
"postprocessors": [
{
"key": "FFmpegExtractAudio",
"preferredcodec": "best",
"preferredquality": 320,
}
],
}
}
}
}
)[1]
)

try:
cmdline_args = (
config._config.get("extractor", {})
.get("ytdl", {})
.get("cmdline-args", [])
)
except AttributeError:
pass
else:
entries_removed.extend(
config.remove(cmdline_args, item="--merge-output-format", value="any")
)

return (entries_added, entries_removed)


if __name__ == "__main__":
run(sys.argv[1], ast.literal_eval(sys.argv[2]))
Loading

0 comments on commit 7108b3c

Please sign in to comment.