عملکردها را با Apps Script API اجرا کنید

API اسکریپت Google Apps یک متد scripts.run ارائه می‌دهد که یک تابع اسکریپت Apps مشخص شده را از راه دور اجرا می‌کند. می‌توانید از این متد در یک برنامه فراخوانی برای اجرای یک تابع در یکی از پروژه‌های اسکریپت خود از راه دور و دریافت پاسخ استفاده کنید.

الزامات

قبل از اینکه یک برنامه‌ی فراخوانی‌کننده بتواند از متد scripts.run استفاده کند، باید الزامات زیر را برآورده کنید. شما باید :

  • پروژه اسکریپت را به عنوان یک فایل اجرایی API مستقر کنید. می‌توانید در صورت نیاز پروژه‌ها را مستقر، لغو استقرار و مجدداً مستقر کنید.

  • یک توکن OAuth با دامنه‌ی دسترسی مناسب برای اجرا ارائه دهید. این توکن OAuth باید تمام دامنه‌های مورد استفاده توسط اسکریپت را پوشش دهد، نه فقط آنهایی که توسط تابع فراخوانی شده استفاده می‌شوند. لیست کامل دامنه‌های دسترسی را در مرجع متد مشاهده کنید.

  • مطمئن شوید که اسکریپت و کلاینت OAuth2 برنامه‌ی فراخوانی‌کننده، یک پروژه‌ی مشترک Google Cloud را به اشتراک می‌گذارند. پروژه‌ی Cloud باید یک پروژه‌ی Cloud استاندارد باشد؛ پروژه‌های پیش‌فرض ایجاد شده برای پروژه‌های Apps Script کافی نیستند. می‌توانید از یک پروژه‌ی Cloud استاندارد جدید یا یک پروژه‌ی موجود استفاده کنید.

  • API اسکریپت برنامه‌های گوگل را در پروژه ابری فعال کنید .

متد scripts.run

متد scripts.run برای اجرا به اطلاعات شناسایی کلید نیاز دارد:

شما می‌توانید به صورت اختیاری اسکریپت خود را طوری پیکربندی کنید که در حالت توسعه اجرا شود. این حالت به جای آخرین نسخه پیاده‌سازی شده، با آخرین نسخه ذخیره شده پروژه اسکریپت اجرا می‌شود. این کار را با تنظیم مقدار بولی devMode در بدنه درخواست به true انجام دهید. فقط مالک اسکریپت می‌تواند آن را در حالت توسعه اجرا کند.

مدیریت انواع داده‌های پارامتری

استفاده از متد scripts.run در API مربوط به Apps Script معمولاً شامل ارسال داده‌ها به Apps Script به عنوان پارامترهای تابع و دریافت داده‌ها به عنوان مقادیر بازگشتی تابع است. API فقط می‌تواند مقادیری با انواع پایه را دریافت و بازگرداند: رشته‌ها، آرایه‌ها، اشیاء، اعداد و مقادیر بولی. این موارد مشابه انواع پایه در جاوا اسکریپت هستند. اشیاء پیچیده‌تر Apps Script مانند Document یا Sheet را نمی‌توان توسط API به پروژه اسکریپت ارسال یا از آن دریافت کرد.

وقتی برنامه‌ی فراخوانی شما به زبانی با نوع داده‌ی قوی مانند جاوا نوشته شده باشد، پارامترها را به صورت یک لیست یا آرایه از اشیاء عمومی مربوط به این انواع پایه ارسال می‌کند. در بسیاری از موارد، می‌توانید تبدیل‌های نوع ساده را به طور خودکار اعمال کنید. به عنوان مثال، می‌توان به تابعی که یک پارامتر عددی می‌گیرد، یک شیء Double یا Integer یا Long جاوا به عنوان پارامتر بدون نیاز به پردازش اضافی داد.

وقتی API پاسخ تابع را برمی‌گرداند، اغلب لازم است قبل از استفاده از مقدار برگشتی، آن را به نوع صحیح تبدیل کنید. در اینجا چند مثال مبتنی بر جاوا آورده شده است:

  • اعدادی که توسط API به یک برنامه جاوا برگردانده می‌شوند، به صورت اشیاء java.math.BigDecimal دریافت می‌شوند و ممکن است در صورت نیاز نیاز به تبدیل به انواع Doubles یا int داشته باشند.
  • اگر تابع Apps Script آرایه‌ای از رشته‌ها را برگرداند، یک برنامه جاوا پاسخ را در یک شیء List<String> قرار می‌دهد:

    List<String> mylist = (List<String>)(op.getResponse().get("result"));
    
  • اگر می‌خواهید آرایه‌ای از Bytes را برگردانید، می‌توانید آرایه را به صورت یک رشته base64 در تابع Apps Script کدگذاری کنید و آن رشته را برگردانید:

    return Utilities.base64Encode(myByteArray); // returns a String.
    

نمونه‌های کد زیر روش‌های تفسیر پاسخ API را نشان می‌دهند.

رویه عمومی

در ادامه، روش کلی استفاده از API مربوط به Apps Script برای اجرای توابع Apps Script شرح داده شده است:

مرحله 1: پروژه ابری مشترک را راه‌اندازی کنید

هم اسکریپت شما و هم برنامه فراخوانی کننده باید یک پروژه ابری مشترک داشته باشند. این پروژه ابری می‌تواند یک پروژه موجود یا یک پروژه جدید ایجاد شده برای این منظور باشد. پس از ایجاد یک پروژه ابری، باید پروژه اسکریپت خود را برای استفاده از آن تغییر دهید .

مرحله ۲: اسکریپت را به عنوان یک فایل اجرایی API مستقر کنید

  1. پروژه Apps Script را با توابعی که می‌خواهید استفاده کنید، باز کنید.
  2. در بالا سمت راست، روی Deploy > New Deployment کلیک کنید.
  3. در کادر محاوره‌ای که باز می‌شود، روی فعال کردن انواع استقرار کلیک کنید > فایل اجرایی API .
  4. در منوی کشویی «چه کسی دسترسی دارد»، کاربرانی را که مجاز به فراخوانی توابع اسکریپت با استفاده از API اسکریپت برنامه‌ها هستند، انتخاب کنید.
  5. روی استقرار کلیک کنید.

مرحله 3: پیکربندی برنامه فراخوانی

برنامه‌ی فراخوانی‌کننده باید API مربوط به Apps Script را فعال کرده و قبل از استفاده، اعتبارنامه‌های OAuth را ایجاد کند. برای انجام این کار باید به پروژه‌ی Cloud دسترسی داشته باشید.

  1. پروژه ابری که برنامه فراخوانی و اسکریپت شما از آن استفاده می‌کند را پیکربندی کنید. می‌توانید این کار را با مراحل زیر انجام دهید:
    1. API مربوط به Apps Script را در پروژه Cloud فعال کنید .
    2. صفحه رضایت OAuth را پیکربندی کنید .
    3. اعتبارنامه‌های OAuth ایجاد کنید .
  2. پروژه اسکریپت را باز کنید و در سمت چپ، روی Overview کلیک کنید. .
  3. در بخش «محدوده‌های پروژه Oauth» ، تمام محدوده‌هایی را که اسکریپت به آنها نیاز دارد، ثبت کنید.
  4. در کد برنامه فراخوانی، یک توکن دسترسی OAuth اسکریپت برای فراخوانی API ایجاد کنید. این توکنی نیست که خود API از آن استفاده کند، بلکه توکنی است که اسکریپت هنگام اجرا به آن نیاز دارد. این توکن باید با استفاده از شناسه کلاینت پروژه Cloud و محدوده‌های اسکریپتی که ثبت کرده‌اید، ساخته شود.

    کتابخانه‌های کلاینت گوگل می‌توانند در ساخت این توکن و مدیریت OAuth برای برنامه بسیار کمک کنند و معمولاً به شما این امکان را می‌دهند که با استفاده از محدوده‌های اسکریپت، یک شیء "credentials" سطح بالاتر بسازید. برای مثال‌هایی از ساخت یک شیء credentials از لیستی از محدوده‌ها، به راهنمای سریع API اسکریپت برنامه‌ها مراجعه کنید.

مرحله ۴: درخواست script.run را ایجاد کنید

پس از پیکربندی برنامه فراخوانی، می‌توانید فراخوانی‌های scripts.run را انجام دهید. هر فراخوانی API شامل مراحل زیر است:

  1. با استفاده از شناسه اسکریپت، نام تابع و هر پارامتر مورد نیاز، یک درخواست API بسازید.
  2. فراخوانی scripts.run را انجام دهید و توکن OAuth اسکریپت را که ساخته‌اید در هدر (اگر از یک درخواست POST ساده استفاده می‌کنید) قرار دهید، یا در غیر این صورت از یک شیء credentials که با محدوده‌های اسکریپت ساخته‌اید استفاده کنید.
  3. اجازه دهید اجرای اسکریپت تمام شود. اسکریپت‌ها می‌توانند تا شش دقیقه زمان اجرا داشته باشند، بنابراین برنامه شما باید این زمان را در نظر بگیرد.
  4. پس از اتمام، تابع اسکریپت ممکن است مقداری را برگرداند که اگر مقدار از نوع پشتیبانی شده باشد، API آن را به برنامه برمی‌گرداند.

می‌توانید نمونه‌هایی از فراخوانی‌های API script.run را در زیر بیابید.

مثال‌های درخواست API

مثال‌های زیر نحوه‌ی ایجاد یک درخواست اجرای API مربوط به Apps Script را به زبان‌های مختلف نشان می‌دهند و یک تابع Apps Script را برای چاپ لیستی از پوشه‌های موجود در دایرکتوری ریشه‌ی کاربر فراخوانی می‌کنند. شناسه‌ی اسکریپت پروژه‌ی Apps Script که شامل تابع اجرا شده است، باید در جایی که با ENTER_YOUR_SCRIPT_ID_HERE مشخص شده است، مشخص شود. این مثال‌ها برای زبان‌های مربوطه به کتابخانه‌های Google API Client متکی هستند.

اسکریپت هدف

تابع موجود در این اسکریپت از Drive API استفاده می‌کند.

شما باید Drive API را در پروژه‌ای که اسکریپت در آن قرار دارد فعال کنید .

علاوه بر این، برنامه‌های فراخوانی باید اعتبارنامه‌های OAuth را ارسال کنند که شامل محدوده Drive زیر است:

  • https://www.googleapis.com/auth/drive

برنامه‌های نمونه در اینجا از کتابخانه‌های کلاینت گوگل برای ساخت اشیاء اعتبارنامه برای OAuth با استفاده از این دامنه استفاده می‌کنند.

/**
 * Return the set of folder names contained in the user's root folder as an
 * object (with folder IDs as keys).
 * @return {Object} A set of folder names keyed by folder ID.
 */
function getFoldersUnderRoot() {
  const root = DriveApp.getRootFolder();
  const folders = root.getFolders();
  const folderSet = {};
  while (folders.hasNext()) {
    const folder = folders.next();
    folderSet[folder.getId()] = folder.getName();
  }
  return folderSet;
}

جاوا


/**
 * Create a HttpRequestInitializer from the given one, except set
 * the HTTP read timeout to be longer than the default (to allow
 * called scripts time to execute).
 *
 * @param {HttpRequestInitializer} requestInitializer the initializer
 *                                 to copy and adjust; typically a Credential object.
 * @return an initializer with an extended read timeout.
 */
private static HttpRequestInitializer setHttpTimeout(
    final HttpRequestInitializer requestInitializer) {
  return new HttpRequestInitializer() {
    @Override
    public void initialize(HttpRequest httpRequest) throws IOException {
      requestInitializer.initialize(httpRequest);
      // This allows the API to call (and avoid timing out on)
      // functions that take up to 6 minutes to complete (the maximum
      // allowed script run time), plus a little overhead.
      httpRequest.setReadTimeout(380000);
    }
  };
}

/**
 * Build and return an authorized Script client service.
 *
 * @param {Credential} credential an authorized Credential object
 * @return an authorized Script client service
 */
public static Script getScriptService() throws IOException {
  Credential credential = authorize();
  return new Script.Builder(
      HTTP_TRANSPORT, JSON_FACTORY, setHttpTimeout(credential))
      .setApplicationName(APPLICATION_NAME)
      .build();
}

/**
 * Interpret an error response returned by the API and return a String
 * summary.
 *
 * @param {Operation} op the Operation returning an error response
 * @return summary of error response, or null if Operation returned no
 * error
 */
public static String getScriptError(Operation op) {
  if (op.getError() == null) {
    return null;
  }

  // Extract the first (and only) set of error details and cast as a Map.
  // The values of this map are the script's 'errorMessage' and
  // 'errorType', and an array of stack trace elements (which also need to
  // be cast as Maps).
  Map<String, Object> detail = op.getError().getDetails().get(0);
  List<Map<String, Object>> stacktrace =
      (List<Map<String, Object>>) detail.get("scriptStackTraceElements");

  java.lang.StringBuilder sb =
      new StringBuilder("\nScript error message: ");
  sb.append(detail.get("errorMessage"));
  sb.append("\nScript error type: ");
  sb.append(detail.get("errorType"));

  if (stacktrace != null) {
    // There may not be a stacktrace if the script didn't start
    // executing.
    sb.append("\nScript error stacktrace:");
    for (Map<String, Object> elem : stacktrace) {
      sb.append("\n  ");
      sb.append(elem.get("function"));
      sb.append(":");
      sb.append(elem.get("lineNumber"));
    }
  }
  sb.append("\n");
  return sb.toString();
}

public static void main(String[] args) throws IOException {
  // ID of the script to call. Acquire this from the Apps Script editor,
  // under Publish > Deploy as API executable.
  String scriptId = "ENTER_YOUR_SCRIPT_ID_HERE";
  Script service = getScriptService();

  // Create an execution request object.
  ExecutionRequest request = new ExecutionRequest()
      .setFunction("getFoldersUnderRoot");

  try {
    // Make the API request.
    Operation op =
        service.scripts().run(scriptId, request).execute();

    // Print results of request.
    if (op.getError() != null) {
      // The API executed, but the script returned an error.
      System.out.println(getScriptError(op));
    } else {
      // The result provided by the API needs to be cast into
      // the correct type, based upon what types the Apps
      // Script function returns. Here, the function returns
      // an Apps Script Object with String keys and values,
      // so must be cast into a Java Map (folderSet).
      Map<String, String> folderSet =
          (Map<String, String>) (op.getResponse().get("result"));
      if (folderSet.size() == 0) {
        System.out.println("No folders returned!");
      } else {
        System.out.println("Folders under your root folder:");
        for (String id : folderSet.keySet()) {
          System.out.printf(
              "\t%s (%s)\n", folderSet.get(id), id);
        }
      }
    }
  } catch (GoogleJsonResponseException e) {
    // The API encountered a problem before the script was called.
    e.printStackTrace(System.out);
  }
}

جاوا اسکریپت

/**
 * Load the API and make an API call.  Display the results on the screen.
 */
function callScriptFunction() {
  const scriptId = '<ENTER_YOUR_SCRIPT_ID_HERE>';

  // Call the Apps Script API run method
  //   'scriptId' is the URL parameter that states what script to run
  //   'resource' describes the run request body (with the function name
  //              to execute)
  try {
    gapi.client.script.scripts.run({
      'scriptId': scriptId,
      'resource': {
        'function': 'getFoldersUnderRoot',
      },
    }).then(function(resp) {
      const result = resp.result;
      if (result.error && result.error.status) {
        // The API encountered a problem before the script
        // started executing.
        appendPre('Error calling API:');
        appendPre(JSON.stringify(result, null, 2));
      } else if (result.error) {
        // The API executed, but the script returned an error.

        // Extract the first (and only) set of error details.
        // The values of this object are the script's 'errorMessage' and
        // 'errorType', and an array of stack trace elements.
        const error = result.error.details[0];
        appendPre('Script error message: ' + error.errorMessage);

        if (error.scriptStackTraceElements) {
          // There may not be a stacktrace if the script didn't start
          // executing.
          appendPre('Script error stacktrace:');
          for (let i = 0; i < error.scriptStackTraceElements.length; i++) {
            const trace = error.scriptStackTraceElements[i];
            appendPre('\t' + trace.function + ':' + trace.lineNumber);
          }
        }
      } else {
        // The structure of the result will depend upon what the Apps
        // Script function returns. Here, the function returns an Apps
        // Script Object with String keys and values, and so the result
        // is treated as a JavaScript object (folderSet).

        const folderSet = result.response.result;
        if (Object.keys(folderSet).length == 0) {
          appendPre('No folders returned!');
        } else {
          appendPre('Folders under your root folder:');
          Object.keys(folderSet).forEach(function(id) {
            appendPre('\t' + folderSet[id] + ' (' + id + ')');
          });
        }
      }
    });
  } catch (err) {
    document.getElementById('content').innerText = err.message;
    return;
  }
}

نود جی اس


import {GoogleAuth} from 'google-auth-library';
import {google} from 'googleapis';

/**
 * Calls an Apps Script function to list the folders in the user's root Drive folder.
 */
async function callAppsScript() {
  // The ID of the Apps Script project to call.
  const scriptId = '1xGOh6wCm7hlIVSVPKm0y_dL-YqetspS5DEVmMzaxd_6AAvI-_u8DSgBT';

  // Authenticate with Google and get an authorized client.
  // TODO (developer): Use an appropriate auth mechanism for your app.
  const auth = new GoogleAuth({
    scopes: 'https://www.googleapis.com/auth/drive',
  });

  // Create a new Apps Script API client.
  const script = google.script({version: 'v1', auth});

  const resp = await script.scripts.run({
    auth,
    requestBody: {
      // The name of the function to call in the Apps Script project.
      function: 'getFoldersUnderRoot',
    },
    scriptId,
  });

  if (resp.data.error?.details?.[0]) {
    // The API executed, but the script returned an error.
    // Extract the error details.
    const error = resp.data.error.details[0];
    console.log(`Script error message: ${error.errorMessage}`);
    console.log('Script error stacktrace:');

    if (error.scriptStackTraceElements) {
      // Log the stack trace.
      for (let i = 0; i < error.scriptStackTraceElements.length; i++) {
        const trace = error.scriptStackTraceElements[i];
        console.log('\t%s: %s', trace.function, trace.lineNumber);
      }
    }
  } else {
    // The script executed successfully.
    // The structure of the response depends on the Apps Script function's return value.
    const folderSet = resp.data.response ?? {};
    if (Object.keys(folderSet).length === 0) {
      console.log('No folders returned!');
    } else {
      console.log('Folders under your root folder:');
      Object.keys(folderSet).forEach((id) => {
        console.log('\t%s (%s)', folderSet[id], id);
      });
    }
  }
}

پایتون

import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError


def main():
  """Runs the sample."""
  # pylint: disable=maybe-no-member
  script_id = "1VFBDoJFy6yb9z7-luOwRv3fCmeNOzILPnR4QVmR0bGJ7gQ3QMPpCW-yt"

  creds, _ = google.auth.default()
  service = build("script", "v1", credentials=creds)

  # Create an execution request object.
  request = {"function": "getFoldersUnderRoot"}

  try:
    # Make the API request.
    response = service.scripts().run(scriptId=script_id, body=request).execute()
    if "error" in response:
      # The API executed, but the script returned an error.
      # Extract the first (and only) set of error details. The values of
      # this object are the script's 'errorMessage' and 'errorType', and
      # a list of stack trace elements.
      error = response["error"]["details"][0]
      print(f"Script error message: {0}.{format(error['errorMessage'])}")

      if "scriptStackTraceElements" in error:
        # There may not be a stacktrace if the script didn't start
        # executing.
        print("Script error stacktrace:")
        for trace in error["scriptStackTraceElements"]:
          print(f"\t{0}: {1}.{format(trace['function'], trace['lineNumber'])}")
    else:
      # The structure of the result depends upon what the Apps Script
      # function returns. Here, the function returns an Apps Script
      # Object with String keys and values, and so the result is
      # treated as a Python dictionary (folder_set).
      folder_set = response["response"].get("result", {})
      if not folder_set:
        print("No folders returned!")
      else:
        print("Folders under your root folder:")
        for folder_id, folder in folder_set.items():
          print(f"\t{0} ({1}).{format(folder, folder_id)}")

  except HttpError as error:
    # The API encountered a problem before the script started executing.
    print(f"An error occurred: {error}")
    print(error.content)


if __name__ == "__main__":
  main()

محدودیت‌ها

API اسکریپت برنامه‌ها چندین محدودیت دارد:

  1. یک پروژه ابری مشترک . اسکریپتی که فراخوانی می‌شود و برنامه فراخوانی‌کننده باید یک پروژه ابری مشترک داشته باشند. پروژه ابری باید یک پروژه ابری استاندارد باشد؛ پروژه‌های پیش‌فرض ایجاد شده برای پروژه‌های اسکریپت برنامه‌ها کافی نیستند. پروژه ابری استاندارد می‌تواند یک پروژه جدید یا یک پروژه موجود باشد.

  2. پارامترهای پایه و انواع بازگشتی . API نمی‌تواند اشیاء مختص اسکریپت برنامه‌ها (مانند Documents ، Blobs ، Calendars ، Drive Files و غیره) را به برنامه ارسال یا ارسال کند. فقط انواع پایه مانند رشته‌ها، آرایه‌ها، اشیاء، اعداد و مقادیر بولی را می‌توان ارسال و ارسال کرد.

  3. دامنه‌های OAuth . این API فقط می‌تواند اسکریپت‌هایی را اجرا کند که حداقل یک دامنه مورد نیاز داشته باشند. این بدان معناست که شما نمی‌توانید از API برای فراخوانی اسکریپتی استفاده کنید که نیازی به مجوز یک یا چند سرویس ندارد.

  4. هیچ تریگری وجود ندارد . API نمی‌تواند تریگرهای اسکریپت برنامه‌ها را ایجاد کند.