Batch update selected extras with selected files?

If you need help on how to use the program
Post Reply
SandBird
Posts: 3
Joined: 2024-12-20 01:54:56

Batch update selected extras with selected files?

Post by SandBird »

Hello,

I am new to this program and find it clutter free, fast and super customizable - I love it! Thank you for making it available!

I was wondering if there is a way to batch update selected extras (or even movies) with different values per extra?

To clarify, here is my scenario:
If I have a list of extras representing episodes that I initially added as place holders, I would like to be able to either update their thumbnail and/or URL with a list of files that I select (by the order I select them); I would like to keep everything else intact - description, titles etc.

And here is what I imagine it would be like:
An initial prompt asking what field you wish to update.
A file selection dialog where you select the files you wish to use to update the field you selected.
Upon confirmation the specified field is being updated with the selected files URLs.

*Another option is maybe use clipboard or a file with a list of items which might be more flexible in case you need to update the titles or description.

Does anyone have an idea how to achieve such a thing?

Any input would greatly appreciated - thank you in advance!
antp
Site Admin
Posts: 9629
Joined: 2002-05-30 10:13:07
Location: Brussels
Contact:

Re: Batch update selected extras with selected files?

Post by antp »

Hi,
The part with the file selection dialog is too advanced for the script capabilities of the program, but for the rest it is maybe possible.
Many kinds of batch-update can be done with the script engine.
There is for example a script "Update Fields (FR-US).ifs" that was made for general changes, but that you can check for some help (though that its comments are in French...)
If you have some programming knowledge, it should not be too difficult to write your own script with that as basis. In the help file of the program there is the list of all available functions in the "Technical info" section (and some are made for handling Extras).
SandBird
Posts: 3
Joined: 2024-12-20 01:54:56

Re: Batch update selected extras with selected files?

Post by SandBird »

Thank you for your reply!

Here is something I made (it was not fully tested but just enough) - first time scripting in Pascal so apologies in advance if some things are a "no-no":

Code: Select all

(***************************************************

Ant Movie Catalog importation script
www.antp.be/software/moviecatalog/

[Infos]
Authors=Ethan Phoenix
Title=Update Selected Extras
Description=Update selected Extras specified field with a list of item wither from folder or a text file.
Site=
Language=Tools
Version=1.0 (1/6/2025)
Requires=4.2.0
Comments=
License=
GetInfo=0
RequiresMovies=1

[Options]
File Mask=0|0|0=Prompt|1=Movies|2=Images
Restore Defaults=0|0|0=No|1=Yes
Enable Warnings=1|1|0=No|1=Yes
Picture Import Method=5|0|0=Prompt|1=Store picture in catalog|2=Copy picture to catalog folder|3=Ccopy picture to pictures folder of catalog|4=Link to picture with absolute link|5=Link to picture with relative link if possible

[Parameters]

***************************************************)

program UpdateSelectedExtras;

var
  extrasFieldSelection, sourcePath, sourceType, itemSelection, mask, picImportMethod, maskSelection : string;
  iSourceItem, iExtras, totalExtras, iExtrasFields, iSelectionID, maskParam : Integer;
  selectedExtrasList, extrasFieldsList, itemsList: TStringList;

// TextBefore function
function TextBefore(wholeText: string; searchText: string): string;
  var
  	foundPos: Integer;
  begin
  	Result := '';
  	foundPos := Pos(searchText, wholeText);
  	if foundPos = 0 then
  		Exit;
  	Result := Copy(wholeText, 0, foundPos-1);
  end;


// SplitString function
function SplitString(InputStr: string; Delimiter: Char): TStringList;
  var
    DelimPos, i: Integer;
    SubStr: string;

  begin
    Result := TStringList.Create; // Create a new TStringList instance
      // Find the first delimiter
    DelimPos := Pos(Delimiter, InputStr);

    // Loop while there are delimiters found
    while DelimPos > 0 do
    begin
      // Extract substring from start position to delimiter position
      SubStr := Copy(InputStr, 0, DelimPos-1);
      Result.Add(SubStr); // Add substring to the TStringList

      Delete(InputStr, 1, DelimPos);

      // Find the next delimiter
      DelimPos := Pos(Delimiter, InputStr);
    end;

    Result.Add(InputStr); // Add substring to the TStringList

    // REMOVING DUPLICATES, JUST IN CASE
    Result.Sort;

    // Iterate backwards through the list
    for i := Result.Count - 1 downto 1 do
    begin
      // Compare the current string with the previous one
      if Result.GetString(i) = Result.GetString(i - 1) then
        Result.Delete(i); // Remove if it's a duplicate
    end;

  end;

// GetItemsList function
function  GetItemsList(sourcePathA: string; maskA: string): TStringList;
  var
    tempItemsList : String;
    i: Integer;
    maskList: TStringList;
  begin
    tempItemsList := '';
    Result := TStringList.Create; // Create a new TStringList instance
    maskList := SplitString(maskA, ';');

    for i := 0 to maskList.Count do
      begin
     		tempItemsList := tempItemsList + ListDirectory(sourcePathA, maskList.GetString(i));
      end;

      Result.Text := tempItemsList;
      Result.Sort;

      maskList.Free;
  end;

// CleanItemsList function
function CleanItemsList(itemsListA: TStringList): TStringList;
  var
    iSourceItem : Integer;
  begin
    Result := TStringList.Create; // Create a new TStringList instance

    for iSourceItem := 0 to itemsListA.Count - 1 do
      Result.Add(TextBefore(itemsListA.GetString(iSourceItem), #9))

		if (Result.GetString(1) = '..') then
      Result.Delete(1)
 		if (Result.GetString(0) = '.') then
      Result.Delete(0)

  end;

// MAIN SCRIPT BEGINS

begin
  // IS RESTORE DEFAULTS SET?

  if (  GetOption('Restore Defaults') = 1) then
    begin
      SetOption('Restore Defaults', 0);
      SetOption('File Mask', 0);
      SetOption('Enable Warnings', 1);
      SetOption('Picture Import Method', 0);
      if (ShowConfirmation('All options restored to their default settings.' + #13#10 +
                           'Do you wish to proceed with the script?') = False) then
        Exit;
    end;

  // MORE THAN ONE MOVIE SELECTED
  if (GetIterationCount <> 1) Then
    begin
      ShowError('This script works on one movie at a time.' + #13#10#13#10 +
      'You can do so by making sure only one movie is selected and selecting "Selected" in the "Script Limitation"' +
      'selection box that can be found at the bottom right area of the Scripting window.');
      Exit;
    end;

  // THERE ARE NO EXTRAS FOR THE SELECTED MOVIE
  if (GetExtraCount = 0) Then
    begin
      ShowError('There are no Extras for the selected movie.' + #13#10#13#10 +
      'This script works with exisiting Extras.');
      Exit;
    end;

  // THERE ARE NO EXTRAS SELECTED
	selectedExtrasList := TStringList.Create;
  totalExtras := GetExtraCount;
  for iExtras := 0 to totalExtras - 1 do
    begin
      if (IsExtraSelected(iExtras) = True) then
        begin
          selectedExtrasList.Add(IntToStr(iExtras));
        end;
    end;

  if (selectedExtrasList.Count = 0) Then
    begin
      ShowError('There are no selected Extras.' + #13#10#13#10 +
      'In order to use this script, please make sure to select at least one Extra.');
      Exit;
    end;

  // SELECTING WHICH EXTRA FIELD TO EDIT
  extrasFieldSelection := '';
	extrasFieldsList := TStringList.Create;
  PickTreeClear;
  PickTreeTitle('Extras Field Selection');
  for iExtrasFields := 0 to GetExtraFieldCount - 1 do
    begin
      if ((GetExtraFieldType(iExtrasFields) = 'ftString') OR
         (GetExtraFieldType(iExtrasFields) = 'ftList') OR
         (GetExtraFieldType(iExtrasFields) = 'ftText') OR
         (GetExtraFieldType(iExtrasFields) = 'ftUrl')) AND
         (iExtrasFields <> ePictureStatus) Then
            PickTreeAdd(GetExtraFieldName(iExtrasFields)+' ('+GetExtraFieldType(iExtrasFields)+')', IntToStr(iExtrasFields));
    end;
    PickTreeAdd('Picture', 'Picture');
    PickTreeSort;
    if (PickTreeExec3('Select from the list below which Extras field you wish to update:', extrasFieldSelection) = False) OR
       (extrasFieldSelection = '') then
        begin
          ShowError('You must select which Extra field you wish to update.');
          Exit;
        end;

  // IF PICTURE, ASK HOW AND/OR SET THE METHOD
  picImportMethod := IntToStr(picImportLinkRel);
  if GetOption('Picture Import Method') = 0 then //Prompt
    begin
      picImportMethod := '-1';
      while (picImportMethod = '-1') do
        begin
          PickTreeClear;
          PickTreeTitle('Pictures Handling Selection');
          PickTreeAdd('Store picture in catalog', IntToStr(picImportStore));
          PickTreeAdd('Copy picture to catalog folder', IntToStr(picImportCopyInCatDir));
          PickTreeAdd('Ccopy picture to pictures folder of catalog', IntToStr(picImportCopyInPicDir));
          PickTreeAdd('Link to picture with absolute link', IntToStr(picImportLinkAbs));
          PickTreeAdd('Link to picture with relative link if possible', IntToStr(picImportLinkRel));
          if (PickTreeExec3('Please select from the list below the method you wish to handle the pictures:', picImportMethod) = False) then
            Exit;
        end
    end
  else if (GetOption('Picture Import Method') = 1) then // picImportStore (store picture into catalog)
    picImportMethod := IntToStr(picImportStore)
  else if (GetOption('Picture Import Method') = 2) then // picImportCopyInCatDir (copy picture into catalog folder)
    picImportMethod := IntToStr(picImportCopyInCatDir)
  else if (GetOption('Picture Import Method') = 3) then // picImportCopyInPicDir (copy picture into pictures folder of catalog)
    picImportMethod := IntToStr(picImportCopyInPicDir)
  else if (GetOption('Picture Import Method') = 4) then // picImportLinkAbs (only link picture with absolute link)
    picImportMethod := IntToStr(picImportLinkAbs)
//  else if (GetOption('Picture Import Method') = 5) then // picImportLinkRel (only link picture with relative link if possible)
//    picImportMethod := IntToStr(picImportLinkRel)


  // ASK FOR SOURCE - FILE OR PATH
  sourcePath := '';
  while (DirectoryExists(sourcePath) <> True) AND (FileExists(sourcePath) <> True) do
    if (Input('Source', 'Please enter a path or a path to a file list you wish to use as a source:', sourcePath) = False) then
      Exit;

  sourceType := '';

  if (DirectoryExists(sourcePath) = True) then
    begin
      sourceType := 'Dir';

      // PROMPT FOR MASK OR TAKE FROM PARAMS
      mask := '';
      maskSelection := '';
      maskParam := GetOption('File Mask');

      if (maskParam = 0) and (extrasFieldSelection <> 'Picture') then
        begin
          PickTreeClear;
          PickTreeTitle('Mask Selection');
          PickTreeAdd('Image Files', '2');
          PickTreeAdd('Video Files', '1');
          PickTreeAdd('Custom', '0');

          if (PickTreeExec3('Select a file mask from the options below to filter the files in the given folder:', maskSelection) = False) then
            Exit
          else
          begin
            if (maskSelection = '0') then
              maskParam := 0
            else if (maskSelection = '1') then
              maskParam := 1
            else if (maskSelection = '2') then
              maskParam := 2;
          end;
        end;

      if (extrasFieldSelection = 'Picture') or (maskParam = 2) then // Images
        mask := '*.bmp;*.gif;*.jpe;*.jpeg;*.jpg;*.png'
      else if (maskParam = 1) then // Movies
        mask := '*.3gp;*.asf;*.avi;*.divx;*.evo;*.flv;*.ifo;*.m2p;*.m2ts;*.m4v;*.mkv;*.mov;*.mp4;*.mpe;*.mpeg;*.mpeg2;*.mpg;*.ogm;*.rm;*.rmvb;*.rv9;*.ts;*.vob;*.wmv;*.xvid'
      else if (maskParam = 0) then // Prompt
        begin
          while (mask = '') do
            Input('Source Mask', 'Please enter a valid mask for the file type(s) you wish to search for (use ; to separate multiple):', mask);
        end;

      itemsList := GetItemsList(sourcePath, mask);
      itemsList := CleanItemsList(itemsList);

    end
  else if (FileExists(sourcePath) = True) then
    begin
      sourceType := 'File';
      itemsList := TStringList.Create;
      itemsList.LoadFromFile(sourcePath);
    end
  else  // WE SHOULDN'T BE HERE BUT JUST IN CASE
    begin
      ShowError('You must select the source you wish to use for updating the selected Extras field.');
      Exit;
    end;

  iSourceItem := 0;
  iSelectionID := -1;
  itemSelection := '';
  while (iSelectionID <> 0) AND (itemsList.Count > 0) do
    begin
      PickTreeClear;
      PickTreeTitle('Source Items Preview:');
      PickTreeAdd('Continue...', '-1');

      for iSourceItem := 0 to itemsList.Count - 1 do
      PickTreeAdd(itemsList.GetString(iSourceItem), IntToStr(iSourceItem));
      if (PickTreeExec4('Select an item below if you wish to remove it, otherwise select "Continue..."', itemSelection, iSelectionID) = True) AND (iSelectionID <> 0) then
        itemsList.Delete(iSelectionID-1)
    end;

    // LET'S CHECK IF THE LIST ISN'T EMPTY
    if (itemsList.Count = 0) then
      begin
        ShowError('The items list is empty, there is nothing that can be assigned to the selected field.');
        Exit;
      end;

  // LET'S CHECK IF THERE IS DISCREPANCY BETWEEN EXTRAS AND ITEMS COUNTS AND PROMPT WARNING
  if (itemsList.Count <> selectedExtrasList.Count) AND (GetOption('Enable Warnings') = 1 )then
      if (ShowWarning('There is a discrepancy between the numbers of selected extras ('+IntToStr(selectedExtrasList.Count)+') and the number of items ('+IntToStr(itemsList.Count)+').'  + #13#10 +
                      'Only the available ones will be assigned, while the excess will be disregarded.' + #13#10#13#10 +
                      'You can disable future messages like this in the Options area of the script under Enable Warnings.') = False) then
                        Exit;


  // WE ARE NOW READY TO UPDATE THE SELECTED FIELD
  for iExtras := 0 to selectedExtrasList.Count - 1 do
    begin
      if extrasFieldSelection = 'Picture' then
        begin
          if (FileExists(IncludeTrailingPathDelimiter(sourcePath)+itemsList.GetString(iExtras)) = True) then
            ImportExtraPicture2(StrToInt(selectedExtrasList.GetString(iExtras),0), IncludeTrailingPathDelimiter(sourcePath)+itemsList.GetString(iExtras), StrToInt(picImportMethod,0))
          else
            if (ShowWarning('Could not locate:'+#13#10+IncludeTrailingPathDelimiter(sourcePath)+itemsList.GetString(iExtras)) = False) then
              Exit;
        end
      else
        begin
          if sourceType = 'File' then
            SetExtraField(StrToInt(selectedExtrasList.GetString(iExtras),0), StrToInt(extrasFieldSelection, 0), itemsList.GetString(iExtras))
          else
            SetExtraField(StrToInt(selectedExtrasList.GetString(iExtras),0), StrToInt(extrasFieldSelection, 0), IncludeTrailingPathDelimiter(sourcePath)+itemsList.GetString(iExtras))
        end;
    end;

  selectedExtrasList.Free;
  extrasFieldsList.Free;
  itemsList.Free;
end.
Thanks again!
SandBird
Posts: 3
Joined: 2024-12-20 01:54:56

Re: Batch update selected extras with selected files?

Post by SandBird »

For anyone who uses the script, I have updated it - I found some errors I overlooked :innocent:
Post Reply