API to create scripts

Hi,

I’m new to Shotgun and currently exploring the Python API.
I was wondering if there are ways to automatize creating new scripts that would avoid having to go over the web interface.
The Python API does not seem to have a ‘Script’ entity type that would allow running sg.create('Script', {...}). Is there another way?

Cheers.

4 Likes

Hi!

The entity name is sometimes different from the displayed name.

In this particular case, scripts are called “ApiUser”. This is what you’ll need to use through the api.

In the web interface, you should be able to see all those entities and their specific settings by going into Shotgun Admin Menu > Site preferences > Entities.

For exemple:

Script (ApiUser)
Used to generate a Key that your API scripts use to connect and login to your Shotgun instance. We recommend using 1 Script per script, which allows you to monitor what each script is doing in the event log (handy when there is a rogue script that is pegging the database).

Cheers

3 Likes

Thanks a lot. This is really helpful.

Is there are preference/guideline for the salting algorithm we should use for the ApiUser password?

2 Likes

Btw, here’s the script. It’s not fully tested yet, but it might be useful to other people.

#!/usr/bin/env python3

import os, sys, re, codecs, site, pprint, datetime
site.addsitedir(os.path.dirname(__file__))
import argparse, keyring, toml, binascii, bcrypt
from pathlib import Path
from password_generator import PasswordGenerator
import colorama
colorama.init()
import qjph.qjph as qjph
qjph.init()

import shotgun_api3

def main(args):
    pp = pprint.PrettyPrinter()
    pp.pprint(args)

    # connect
    sg1 = shotgun_api3.Shotgun(args.site, Path(__file__).stem, args.key)
    pp.pprint(sg1.schema_field_read('ApiUser'))

    # retrieve current user
    user = sg1.authenticate_human_user(args.user, args.password)
    pp.pprint(user)
    assert(user)

    script_fields = ['id', 'description', 'cached_display_name', 'firstname', 'lastname', 'salted_password', 'projects']

    scripts = sg1.find('ApiUser', filters=[['id', 'is_not', 0]], fields=script_fields)
    pp.pprint(scripts)

    existing_script = sg1.find_one('ApiUser', filters=[['firstname', 'is', args.scriptname]], fields=script_fields)

    if existing_script:
        print(f"a script named {args.scriptname} already exists.")
        pp.pprint(existing_script)
        print("Please choose a different name and try again.")
        exit(0)

    saltedpw = str(bcrypt.hashpw(PasswordGenerator().generate().encode(), bcrypt.gensalt()))
    print(saltedpw)

    nscript = sg1.create('ApiUser', {
        'firstname': args.scriptname,
        'description': args.description,
        'salted_password': saltedpw,
    }, return_fields=script_fields)
    pp.pprint(nscript)

    print(f"Created new script {nscript['cached_display_name']}")
    print(f"API key: {saltedpw}")

if __name__ == '__main__':
    config = qjph.load(Path(__file__).with_suffix('.json'))
    parser = argparse.ArgumentParser(description='Shotgun API Test 4: Create Scripts')
    parser.add_argument('-s', '--site', help='site name', type=str, default=config['site'])
    parser.add_argument('-k', '--key', help='api key', type=str, default=config['key'])
    parser.add_argument('-u', '--user', help='username', type=str, default=config['user'])
    parser.add_argument('-p', '--password', help='password', type=str, default="")
    parser.add_argument('scriptname', help='script name', type=str)
    parser.add_argument('-d', '--description', help='script description', type=str, default="")
    args = parser.parse_args()
    if not args.password or args.password == "":
        args.password = keyring.get_password(args.site, args.user)
        """
        Note: need to store password like this
        ```sh
        python3 -m keyring set <site> <user>
        ## then enter password in prompt
        ```
        """
    main(args)

Cheers.

2 Likes