GithubHelp home page GithubHelp logo

rlaphoenix / pynfogen Goto Github PK

View Code? Open in Web Editor NEW
35.0 3.0 5.0 375 KB

Scriptable MediaInfo-fed NFO Generator for Movies and TV

License: MIT License

Python 100.00%
nfo generator scriptable python mediainfo

pynfogen's Introduction

pynfogen

License Build status Python version PyPI version DeepSource issues

Scriptable MediaInfo-fed NFO Generator for Movies and TV.

Installation

pip install --user pynfogen

F.A.Q

Using pynfogen is fairly simple, it's a multi-command CLI program. You can see up-to-date help information by running nfo --help, or reading the readme file.

On initial installation, you won't have any Artwork or Templates, which are needed. You can take a look at some examples at /examples/art and /examples/templates in the git. You may also want to take a look at Configuration.

Once you have everything set up as much as you want, simply take a look at the available commands with nfo --help. The main command you want to take a look at would be nfo generate -h, which will create NFO and Description files based on one provided video file.

What is an NFO and Description file, you may ask? tl-dr; Think of an NFO as a Receipt with information about your release to be shared alongside it, and a Description file as the body for your post, thread, topic, message, or such. You could also think of a Description file as an alternative output you could use.

More information can be found in the sections below.

What is an NFO?

An NFO (aka .nfo, .NFO, a contraction of "Info" or "Information") is a commonly used filename extension for text files that accompany various releases with information about them.

They are for delivering release information about the media, such as the title, release date, authorship, etc. They also commonly contain elaborate ANSI art.

An NFO is generally archaic, do not think otherwise. Originally, NFO files would be shared through IRC, Usenet, Email, etc. However, these days, most platforms do not allow NFO files to be shared with the release itself, but rather within a forum thread or post. NFOs are becoming more and more phased out in P2P sharing, but still remains in use in some cases.

While there isn't any hard-rules, If you plan to create a modern-style NFO then the following is recommended:

  • Max line-length of 70 characters.
  • Text should not reach the edge of the file (col. 1 and 70), instead it should be padded by spacing or ANSI art.
  • Text-encoding should be UTF-8 and not CP437. CP437 is far too restricted compared to UTF-8.

Note that, elaborate ANSI art is no longer really used or wanted. Modern NFO files tend to be verbose with minimal ANSI art, rather than concise with elaborate ANSI art.

What is a Description file?

It's like an NFO, without any rules whatsoever. You can use a description template as an alternative output to the NFO output. This alternative output can be used for any purpose you like, but most commonly used for forum posts, IRC messages, and such.

What file should I pass to nfo generate?

It's best-practice to provide the first-most file that best represents the majority of the release. E.g., If Episode 1 and 2 has a fault not found on Episodes 3 onwards, then provide Episode 3.

What Text-encoding is supported?

The input file templates and artwork must be UTF-8. The output generated files' text-encoding can be chosen by you, but defaults to UTF-8.

To choose a text-encoding for the output, see -e/--encoding of nfo generate. This can also be set in the config with nfo config generate.encoding cp437 (sets to CP437).

NFOs with elaborate ANSI art may need to use CP437 text-encoding, where-as any other NFO can get away with just about any encoding. The default UTF-8 will work fine for most scenarios. However, some applications or websites may require your NFO to be a specific text-encoding, which is usually either CP437 or UTF-8.

How is it detecting or getting ...?

Database IDs (IMDB, TMDB, TVDB)

CLI options (-imdb, -tmdb, -tvdb), the Config, or the provided file's global tags (in that order).

Title Name and Year

The IMDB page's <title> tag for the provided IMDB ID.

Release Name

Season releases get it from the parent folder name of the provided file. Movie and Episode releases get it from the filename.

Preview Images

It scrapes the provided Preview URL (-P) for thumbnail and full image URLs. The Preview URL must be for a Gallery or Album. Supported hosts:

Banner Image

The Fanart.tv API if a TVDB ID has been provided, and a Fanart.tv API key has been set. It only returns banners that match the language of the primary Audio tracks language.

Season Episode Count

It counts the amount of neighbouring files of the same file-extension as the provided file. Make sure all files matching this check is going to be part of the release as an episode file, or the episode count will be inaccurate.

Templates

Type Description File Extension
NFO Template Primary Scriptable, structural data, like the Title, Year, Media Information, etc. .nfo
Description Template Similar to NFO templates, but for the content of a forum post, IRC message, etc. .desc.txt

You can add, delete, edit, and list templates with nfo template -h.

Tip: If you notice you are copying and pasting something between templates that is not structural or media information, then you should probably put it into an Artwork instead.

Artwork

Artworks are for surrounding an NFO templates generated output with artwork or common text. Artwork templates aren't currently applied to Description templates.

You can add, delete, edit, and list artwork with nfo artwork -h.

Important: The provided example Artwork files are for viewing and studying only, for more information see their LICENSE.

Configuration

All configuration values is entirely optional, but may require to be set to enable some features.

Configuration values can be set with nfo config, e.g., nfo config generate.artwork phoenix. See nfo config -h for more information.

Config Key Description
fanart_api_key A Fanart.tv API Key to use for the fanart banner image (if available)
generate.* Allows you to set a default for any of the arguments in use by nfo generate

Scripting

The scripting system used by pynfogen is by no means ideal. It is however, consistent. It's mostly a mix of python's normal new-style string formatting, with custom formatters. It also uses a PHP-like <?{x:y}..?> custom syntax for if statements.

Scripting is generally not recommended to be used within Artwork templates.

If statement

For example the following will check if the {note} variable (python new-style formatting) is a truthy value, and only if so, print it:

# note = "Hello World!"
<?{note:true}?Has note: {note}?>
# returns: `Has note: Hello World!`

# note = ""  # or None, 0, False, 1==2, e.t.c
<?{note:true}?Has note: {note}?>
# returns: ``

It's obvious this is in no way good syntax for if statements (no else or elif support either), but it works.

It uses 1 and 0 in the <?{here}?...> section to determine if it should print or not. Essentially speaking any time the If statement is used, you should be using the Boolean custom formatter.

Custom Formatting

The following custom additional formatting to pythons new-style formatting is available:

Chaining

Example: {var:bbimg:layout,2x2x0}

Using : you can chain formatter results from left to right, passing previous value as it goes on. The previous value does not necessarily need to be used.

For less confusion, since : is already used as standard in new-string formatting, look at the above example as {(var:bbimg):(layout,2x2x0)}

Boolean

Example: {var:true} or {var:!false}.
Type-hint: func(var: Any) -> Fixed[1, 0]

Returns 1 if var is a truthy value, otherwise 0.

There's also {var:false} and {var:!true} which is the flip-reverse of the above result.

BBCode Image Links

Example: {var:bbimg}
Type-hint: bbimg(var: Union[List[dict], dict]) -> Union[List[str], str]
Each dictionary: e.g. {url: 'https://url/to/image/page', src: 'https://url/to/image/src.png'}

Every dictionary is converted to BBCode [IMG] wrapped in [URL]. For example: [URL=https://url/to/image/page][IMG]https://url/to/image/src.png[/IMG][/URL]

Returns a list of converted bbcode strings, or a single string if only one dictionary was provided.

Layout

Example: {var:layout,3x2x1}
Type-hint: layout(var: Union[List[Any], Any], width: int, height: int, spacing: int) -> str

Lays out items in a grid-like layout, spacing out items using spaces (or new lines) as specified. New-lines are used when spacing vertically.

Wrapping

Example: {var:>>2x68}
Type-hint: wrap(var: Any, indent: int, wrap: int)

Text-wrap to a specific length. Each subsequent new-line caused by the wrapping can be intended (or not if 0).

Centering

Example: {var:^>70x68}
Type-hint: center(var: Any, centering: int, wrap: int)

Centers and also Text-wraps (while also centering wraps) to a specific width.

License

MIT License

pynfogen's People

Contributors

dependabot[bot] avatar rlaphoenix avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

pynfogen's Issues

TypeError: string indices must be integers

> nfo generate -tvdb 305074 -imdb tt5626028 My.Hero.Academia.S06E01.1080p.CR.WEB-DL.DDP2.0.H.264-GROUP.mkv episode 1 "My Hero Academia" 6
Traceback (most recent call last):
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\Scripts\nfo.exe\__main__.py", line 7, in <module>
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\site-packages\click\core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\site-packages\click\core.py", line 1055, in main
    rv = self.invoke(ctx)
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\site-packages\click\core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\site-packages\click\core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\site-packages\click\core.py", line 1626, in _process_result
    value = ctx.invoke(self._result_callback, value, **ctx.params)
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\site-packages\click\core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\site-packages\click\decorators.py", line 26, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\site-packages\pynfogen\cli\generate.py", line 122, in generator
    nfo_txt = nfo.run(template_text, art=artwork_text, **template_vars)
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\site-packages\pynfogen\nfo.py", line 116, in run
    template = CustomFormats().format(template, **variables)
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\string.py", line 161, in format
    return self.vformat(format_string, args, kwargs)
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\string.py", line 165, in vformat
    result, _ = self._vformat(format_string, args, kwargs, used_args, 2)
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\string.py", line 205, in _vformat
    obj, arg_used = self.get_field(field_name, args, kwargs)
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\string.py", line 278, in get_field
    obj = obj[i]
TypeError: string indices must be integers

LookupError exception if a track has no language tag, or an invalid tag

This commonly occurs on the video track, as some people believe videos do not have language, yet they really do. Language can be defined by the on-screen text like the small credits that roll by at the start of the video, credits at the end of the video, signposts, letters, etc.

It's also common for media to have different masters per language, e.g. a lot of anime. Specifying one is always recommended.

I'm not suggesting the language check should be ignored, rather a helpful message should be printed when it occurs instead of crashing.

Traceback (most recent call last):
  File "/home/user/.nfo/bin/nfo", line 8, in <module>
    sys.exit(cli())
  File "/home/user/.nfo/lib/python3.8/site-packages/click/core.py", line 1137, in __call__
    return self.main(*args, **kwargs)
  File "/home/user/.nfo/lib/python3.8/site-packages/click/core.py", line 1062, in main
    rv = self.invoke(ctx)
  File "/home/user/.nfo/lib/python3.8/site-packages/click/core.py", line 1668, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/user/.nfo/lib/python3.8/site-packages/click/core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/user/.nfo/lib/python3.8/site-packages/click/core.py", line 763, in invoke
    return __callback(*args, **kwargs)
  File "/home/user/.nfo/lib/python3.8/site-packages/click/decorators.py", line 38, in new_func
    return f(get_current_context().obj, *args, **kwargs)
  File "/home/user/.nfo/lib/python3.8/site-packages/pynfogen/cli/generate.py", line 69, in generate
    "videos_pretty": nfo.get_video_print(nfo.videos),
  File "/home/user/.nfo/lib/python3.8/site-packages/pynfogen/nfo.py", line 209, in get_video_print
    l1 = f"- {pycountry.languages.get(alpha_2=t.language).name}, {codec} " + \
  File "/home/user/.nfo/lib/python3.8/site-packages/pycountry/db.py", line 41, in load_if_needed
    return f(self, *args, **kw)
  File "/home/user/.nfo/lib/python3.8/site-packages/pycountry/db.py", line 110, in get
    raise LookupError()
LookupError

Ability to choose output text-encoding

Currently, it reads and writes files with the OS default text-encoding. It may be wanted to use a specific text-encoding for the output NFO file. Maybe not required for the description file though, as those would be shared to places where UTF-8 would be the norm.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.