[Epic] Setting up AMC with qbittorrent, an AAR

Running FileBot from the console, Groovy scripting, shell scripts, etc
Post Reply
dem61s
Power User
Posts: 5
Joined: 29 Oct 2015, 23:04

[Epic] Setting up AMC with qbittorrent, an AAR

Post by dem61s »

Everybody likes a good story. Few people enjoy mines. I rarely have good ones. And yet, I have found a way to tell stories anyway. Humans are built a certain way. There are few things as delectable to them as hearing about the miseries of others. Today, Mr. filebot punched me right on the mouth, so that's what I'm gonna be writing about. Hopefully it will make a few people chuckle.

Read on if you dare. Or, perhaps more accurately, if you have time to waste.

After Action Report: Setting up AMC in qbittorrent
A story of pain and hurt, loosely based on reality

System requirements

Why would anybody even start such a journey? Masochistic tendencies aside, the basic ingredients are as follows, in summary:
  • Step 1: Contract an addiction to TV shows.
  • Step 2: Get fed up with utorrent and use qbittorrent as your primary means for feeding your addiction.
  • Step 3: While rss feeds work well enough to automate downloads, using your download client as a media manager should get old very quickly. Especially if you make a habit of renaming every file manually.
  • Step 4: Install a plex server and try using Sonarr and CouchPotato to the media managing (and possibly replace the way you feed torrent to your download client).
  • Step 5: Run into into all kinds of hell because of their lack of support for qbittorrent (for Sonarr) and possibly being a little green at handling torrents as well (especially CouchPotato)
  • Step 6: Come to the conclusion that the downloading part was working just fine so far and that what you actually need is the merely the renaming / metadata fetching part of the system.
At this stage, you should be ready to start your filebot -AMC journey. Or, more accurately, your -script fn:AMC journey. It is anyone's guess why filebot will not take an AMC argument right of the bat. I would wager that this has to do with that rednoah character that seems to be all over the filebot boards. If you take a good look at him, you can see that he looks shifty anyway:

Image


Henceforth, you shall be known as...

As far as I can remember, I have always loved naming stuff. It started with giving clever nicknames to my friends. I would usually realize later that many of those nicknames were not so clever after all. It never stopped me from going on. This is the nature of naming things after all.

Some will be perfectly content using one's given name. I am not. The same principle applies to my media. I name them.

For movies, it always seemed like a good starting place was:
Media/Movies/<title> (<year>) [<tags>]/<title> (<year>).<ext>

One is always entitled to have strong opinions on what would constitute a tag, of course. One is also welcome to change his mind over time on the issue, and to hold his new opinion as strongly as the previous one, of course. I have currently taken the view that keeping them to a minimum was advisable. Considering that the release group almost always provided me with enough information about the encoding, I elected to use it. I would merely add a secondary information allowing me to differentiate between the different releases of the same group. Incidentally, my preference would be that this addition had the approval of whatever person (friend or foe) may come across my media library to avoid unwelcome conversations about my naming habits. That is how I settled for the following tags:
[<1080p/720p/480p>,<release group>]

Mr. filebot was kind enough to provide a few examples about the way things could work out. It seemed that the proper way to go would be:

Code: Select all

[{vf},{group}]
Unfortunately, after extensive testing, it seemed that {vf} would remain pretty much unknown for every file I would test. Would I settle for another information? Attempt to parse the information myself from the file path? Both possibilities were researched and worked out in detail, until I came to the realization that my Java merely required 32 more bits to function that what I provided him with. So I welcomed the 64 bits version home and cursed Mr. filebot for not warning me about this issue.

Little did I know that this was only the beginning of my headaches. After my earlier experience with missing fields, I was not about to settle for a naming convention that would not be appropriate should any number of fields remain missing. This quest proved very painful. I grew accustomed to [], [,], [<insert random and extremely unhelpful error message>]. I was not quite ready to abandon though and after much perusing on those boards, I finally came up with:

Code: Select all

{allOf{vf}{group} ? " [" + allOf{vf}{group}.join(",") + "]" : ""} 
While this still looks incredibly awkward to me, it does seem to do the job. I would thank Mr. rednoah for his helpful comments I found here during my readings. But I shall not. He is, as mentioned earlier, quite a shifty character after all.

At this stage, an incredible idea struck me: why did I not use this helpful allOf all along, for the other parts of the name as well? And I do mean all of them. I could not find any good answer to this question. Therefore, I settled on the following movie naming scheme:

Code: Select all

{allOf 
  {"Movies"} 
  {allOf 
    {n.replaceAll(/[!?.]+$/).replaceAll(/[`´‘’?]/, "'")} 
    {" (" + y + ")"} 
    {allOf{vf}{group} ? " [" + allOf{vf}{group}.join(",") + "]" : ""} 
  .join()} 
  {allOf 
    {n.replaceAll(/[!?.]+$/).replaceAll(/[`´‘’?]/, "'")} {"(" + y + ")"} 
    {"CD"+pi}
    {lang} 
  .join(" ")} 
.join("/")}
With quite a bit of assistance from allOf again and a few helpful posts from a shifty character that should remain unnamed, TV shows were given a name as well:

Code: Select all

{allOf 
  {"TV Shows"} 
  {n.replaceAll(/[!?.]+$/).replaceAll(/[`´‘’?]/, "'")} 
  {allOf 
    {n.replaceAll(/[!?.]+$/).replaceAll(/[`´‘’?]/, "'")} 
    {episode.special ? "Specials" : "s"+s.pad(2)} 
  .join(" - ")} 
  {allOf 
    {n.replaceAll(/[!?.]+$/).replaceAll(/[`´‘’?]/, "'")} 
    {episode.special ? airdate : s00e00.lower()} 
    {t.replaceAll(/[`´‘’?]/, "'").replaceAll(/[!?.]+$/).replacePart(", Part $1")}  
  .join(" - ")} 
.join("/")}

Getting acquainted with Mr. AMC

As a matter of principles, it seemed fairly obvious though that allowing Mr. AMC to blindly rename everything was not going to be an agreeable proposal. He would only be allowed to toy with those torrents that were tagged as either movies or TV shows. Unfortunately, I soon found out that Mr. qbittorrent would not provide me with this kind of information. He can be a bit of a asshole at times... Since he does allow sorting downloads neatly in folders that match their tags, I would have to parse the information required from the file path.

Now ready to name names, it was time for me to have a chat with Mr. AMC. So I started reading up on him. Little known facts about him include:
  • Despite claims to the contrary (made by a shity character), tagging files is not the only way to force Mr. AMC into a certain mode (Movies/TV Shows). Mr. AMC is just as attentive to what is in the file path. This detail has its importance (and added benefits) when dealing with Mr. qbittorrent who will append tags to the path but not disclose them out loud.
  • Mr. AMC will talk to Mr. MyEpisodes.com it would seem, but not to Mr. Trackt.tv. That is unusual these days. Not to worry about though. Mr. Trackt.tv has become kind of a 2.0 jerk in recent times I am afraid.
  • After much syntaxic battling with Mr. AMC, I found out that --filter, when not returning an error, would not filter out input files but would rather filter out search results. That was an unfortunate amount of headaches for very little results.
Upon further investigation, it became clear that, while Mr. AMC would let us --def ignore certain files, he would not willingly let himself be allowed only to predefined sub-directories of the download folder. Confrontation with Mr. AMC was now all but unavoidable.


Escaping

Far from being discouraged by Mr. AMC's grab for power, I decided that the best course of action would to show him the middle finger and I decided to find a way to only call him when I wanted. And that is how I ended up contacting Mr. batch. Unfortunately, he talks an awful language that I have trouble understanding. With a whole lot of efforts, we finally managed to understand each other. The most irritating thing with this Mr. batch is that he would only engage in a conversation if I agreed to escape. All the fucking time. Escaping is pretty much all I did actually. Here is how the conversation finally went:

Code: Select all

:: Runs filebot on completion of a download in qbittorrent
:: intended to be launched as qb_run_on_completion.bat %f within qbittorrent
@ECHO OFF
^
SET TV_SHOWs="TV Shows"
SET MOVIES="Movies"
:: Remove TV Shows and Movies from the path supplied in %1
SET REMOVE_TV_SHOWS=%~1:TV_SHOWS=%
SET REMOVE_MOVIES=%REMOVE_TV_SHOWS:MOVIES=%
^
:: If something has been removed, we are either in the TV Shows or Movies subfolders
:: So we can run filebot
IF NOT REMOVE_MOVIES == %~1 (
^
filebot.launcher.exe ^
^
-script fn:amc ^
--output "D:/Media" ^
--log-file "D:/Thomas/Downloads/Torrents/amc.log" ^
--action hardlink ^
--conflict auto ^
-non-strict ^
^
--def "seriesFormat= {allOf {\"TV Shows\"} {n.replaceAll(/[!?.]+$/).replaceAll(/[`´‘’?]/, \"'\")} {allOf {n.replaceAll(/[!?.]+$/).replaceAll(/[`´‘’?]/, \"'\")} {episode.special ? \"Specials\" : \"s\"+s.pad(2)} .join(\" - \")} {allOf {n.replaceAll(/[!?.]+$/).replaceAll(/[`´‘’?]/, \"'\")} {episode.special ? airdate : s00e00.lower()} {t.replaceAll(/[`´‘’?]/, \"'\").replaceAll(/[!?.]+$/).replacePart(\", Part \$1\")}  .join(\" - \")} .join(\"/\")}" ^
^
--def "movieFormat= {allOf {\"Movies\"} {allOf {n.replaceAll(/[!?.]+$/).replaceAll(/[`´‘’?]/, \"'\")} {\" (\" + y + \")\"} {allOf{vf}{group} ? \" [\" + allOf{vf}{group}.join(\",\") + \"]\" : \"\"} .join()} {allOf {n.replaceAll(/[!?.]+$/).replaceAll(/[`´‘’?]/, \"'\")} {\"(\" + y + \")\"} {\"CD\"+pi}{lang} .join(\" \")} .join(\"/\")}" ^
^
--def music=n ^
--def plex=localhost:SbeBJk7L8joGmnaVfeWX ^
--def exludeList="D:/Thomas/Downloads/Torrents/amc.txt" ^
--def "%~1"
)

Onward

While my account of this adventure will seem a bit odd, it will pale in comparison with this: after so much effort, I only ever tried --action test...

Any story about naming and processing meta data and/or subtitles for my entire library will have to await further adventures. I would rather not try and fetch them on a torrent completion. Any good script for that? Spotted any crappy scripting on my part? Please let me know. I may or may not be open to shifty suggestions.

:p
dem61s
Power User
Posts: 5
Joined: 29 Oct 2015, 23:04

Re: [Epic] Setting up AMC with qbittorrent, an AAR

Post by dem61s »

A short update

After additional discussions with Mr. filebot, it seems he accepts words like $(null) to be thrown at him. Therefore, the following section of the movie naming scheme:

Code: Select all

  {allOf
    {n.replaceAll(/[!?.]+$/).replaceAll(/[`´‘’?]/, "'")}
    {" (" + y + ")"}
    {allOf{vf}{group} ? " [" + allOf{vf}{group}.join(",") + "]" : ""}
  .join()} 
has been replaced by:

Code: Select all

  {allOf
    {n.replaceAll(/[!?.]+$/).replaceAll(/[`´‘’?]/, "'")}
    {"(" + y + ")"}
    {allOf{vf}{group} ? "[" + allOf{vf}{group}.join(",") + "]" : $(null)}
  .join(" ")} 
While it changes nothing to the actual output, it does increase the elegance of the name.
User avatar
rednoah
The Source
Posts: 23924
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: [Epic] Setting up AMC with qbittorrent, an AAR

Post by rednoah »

While enjoying the opening of this grand epic, and looking forward to the continuation, I am, unfortunately not one of the witty ones here... So all I can add is some shifty commentary.

At this stage, you should be ready to start your filebot -AMC journey. Or, more accurately, your -script fn:AMC journey. It is anyone's guess why filebot will not take an AMC argument right of the bat.
Well... filebot -script fn:amc is short for filebot -script https://raw.githubusercontent.com/fileb ... amc.groovy so it's good to know something shifty is going on, especially when fetching and running code (which may change over time) from GitHub. ;)

Henceforth, you shall be known as...
I expect to be named before this ends. In the meanwhile, I ranked you, cause I rank things.

So I welcomed the 64 bits version home and cursed Mr. filebot for not warning me about this issue.
Well... it's in the FAQ, and there should be a warning about not being able to load 64-bit libraries. Oh well, 32-bit code is going a away eventually, right? Right? Maybe? Please? I give up...

While this still looks incredibly awkward to me, it does seem to do the job. I would thank Mr. rednoah for his helpful comments I found here during my readings. But I shall not. He is, as mentioned earlier, quite a shifty character after all.
If you account for the awkward cases like {vf} being undefined (e.g. corrupt video file) which can't (read: shouldn't) happen, then things do get more awkward with every rare corner-case, such is the price of perfection. Also, you're very welcome.

At this stage, an incredible idea struck me: why did I not use this helpful allOf all along, for the other parts of the name as well? And I do mean all of them. I could not find any good answer to this question.

There is none. That's how the elite few write their formats, in code, and code only. :ugeek:

For the sake of competition, and since writing formats is one of the more fun things to do around here, ...

Code: Select all

{
[
	['Movies']
	,
	allOf
		{n}
		{'(' + y + ')'}
		{ allOf{vf}{group} }
	,
	allOf
		{n}
		{'(' + y + ')'}
		{'CD'+pi}
		{lang}
]
*.findResults{ 
		if (it) it
			.toString()
			.replaceAll(/[!?.]+$/)
			.replaceAll(/[`´‘’?]/, /'/)
}
*.join(' ')
.join('/')
}
The nice thing about the 1-expression-1-format style is that you can do all your clean up in one place at the end for all variables. Also, I'd avoid using double-quotes "..." if you already know that you're gonna have to escape them.

Now ready to name names, it was time for me to have a chat with Mr. AMC. So I started reading up on him. Little known facts about him include:
  • Despite claims to the contrary (made by a shity character), tagging files is not the only way to force Mr. AMC into a certain mode (Movies/TV Shows). Mr. AMC is just as attentive to what is in the file path. This detail has its importance (and added benefits) when dealing with Mr. qbittorrent who will append tags to the path but not disclose them out loud.
  • Mr. AMC will talk to Mr. MyEpisodes.com it would seem, but not to Mr. Trackt.tv. That is unusual these days. Not to worry about though. Mr. Trackt.tv has become kind of a 2.0 jerk in recent times I am afraid.
1. In an ideal world, the need for label support in post processing scripts, and the lack thereof, should lead the qbittorrent devs to add support for that... In the real world I constantly add rules to the forceXYZ rules.
2. MyEpisodes.com has been discontinued years ago, but somehow it just kept working... well, until recently, now it's dead. Not sure if I'm interested into adding anything like that ever again. I'll leave that to the community.

Upon further investigation, it became clear that, while Mr. AMC would let us --def ignore certain files, he would not willingly let himself be allowed only to predefined sub-directories of the download folder. Confrontation with Mr. AMC was now all but unavoidable.
Negative regular expression rules are ugly bitches, but not impossible.

I'd start the --def ignore pattern with your output folder, and then do a negative look-ahead for your tv/movie folders. That should exclude everything else.

contacting Mr. batch.
Never ever has that been a good idea.

he talks an awful language that I have trouble understanding
I skipped that part. Too many traumatizing memories.

I only ever tried --action test...
I sure hope the output of that looks at least somewhat promising! :lol:

I would rather not try and fetch them on a torrent completion.
Why not? The amc script will only allow you to search for subtitles by hash (strict mode) so the only problem you might encounter is not being able to get subtitles at the time.

Any good script for that?
There is a script, I'm not sure if it's a good one. :P

Shifty folks would use the amc script to get subtitles immediately if possible, and then have the suball script run on a schedule once a day to search for more subtitles (in non-strict mode) for all files older than 1 day (so there should be good subtitles) but less old than 7 days (since there probably won't ever be any at this). Keep in mind that there's a daily limit of subtitles you can download from OpenSubtitles. ;)
:idea: Please read the FAQ and How to Request Help.
dem61s
Power User
Posts: 5
Joined: 29 Oct 2015, 23:04

Re: [Epic] Setting up AMC with qbittorrent, an AAR

Post by dem61s »

The Shifty One wrote:I expect to be named before this ends.
I would have thought I settled this issue already. But for now, I will keep your name a secret. Although I may leave a clue or two.
rednoah wrote:In the meanwhile, I ranked you, cause I rank things.
Best not to deny ourselves the few little pleasures we have. I can feel the power already.
rednoah wrote:it's in the FAQ, and there should be a warning about not being able to load 64-bit libraries.
Perhaps I was not entirely honest and I did read the FAQ. And perhaps I was entirely conviced that I had already both 32 and 64 bits versions running.
Or perhaps I would never stray from the truth even to write a little story. We will never know!
rednoah wrote:If you account for the awkward cases like {vf} being undefined
At this point, I am afraid I have to account for all the cases where I banged my head on a problem which has no practical application. I find that the only satisfying way to deal with such an issue is to stick your fingers in your hears and start humming very loudly to pretend that you did not hear anything of those issues.
The process may sound a bit shifty, but I am sure you will understand.
The Shifty One wrote:The nice thing about the 1-expression-1-format style is that you can do all your clean up in one place at the end for all variables.
Now, why did I not think of that in the first place? You are just trying to make me look bad... I will shamelessly steal that idea from you and pretend it was my own!
rednoah wrote:I'd start the --def ignore pattern with your output folder, and then do a negative look-ahead for your tv/movie folders. That should exclude everything else.
That actually sounds more impracticle then looking for the tv/movie folders inside a batch file before calling filebot. :o

The way I see it, I may end up using a batch file anyway, even if it only calls filebot and could just as well be done inside my download client. The reason is: when I spend a shit ton of time figuring out what syntax I want to use to call Mr. filebot, I don't want that syntax burried inside a random config file somewhere. I prefer having it separate and backed up.
rednoah wrote:The amc script will only allow you to search for subtitles by hash (strict mode) so the only problem you might encounter is not being able to get subtitles at the time.
I am only ever interested in subtitles for those shows/movies that I will store in my library for a while. For everything that I will be the only one watching and deleting shortly after, I do not bother with subtitles.
Although I could just as well download subtitles for everything I suppose. Or maintain a list and check against it. :effort:

Ultimately, my worry is as much about various artwork as it is with subtitles. I pick, name and organize my artwork with as much care as my video files. Even theme songs. I will not have a script mess up my artwork!

But yeah, I will have to figure something out for both subtitles and artwork now. I had my mind set on handling artwork separately from the renaming part. It certainly doesn't have to be that way for subtitles.
Post Reply