You are here

zoomapi.module in Zoom API 7

Same filename and directory in other branches
  1. 7.2 zoomapi.module

Main file for the Zoom API module.

File

zoomapi.module
View source
<?php

/**
 * @file
 * Main file for the Zoom API module.
 */
define('ZOOMAPI_USER_TYPE_BASIC', 1);
define('ZOOMAPI_USER_TYPE_PRO', 2);
define('ZOOMAPI_USER_TYPE_CORP', 3);
define('ZOOMAPI_USER_TYPE_DEFAULT', ZOOMAPI_USER_TYPE_BASIC);
define('ZOOMAPI_MEETING_TYPE_INSTANT', 1);
define('ZOOMAPI_MEETING_TYPE_NORMAL', 2);
define('ZOOMAPI_MEETING_TYPE_RECURRING_NO_FIXED_TIME', 3);
define('ZOOMAPI_MEETING_TYPE_RECURRING_FIXED_TIME', 8);
define('ZOOMAPI_MEETING_TYPE_DEFAULT', ZOOMAPI_MEETING_TYPE_NORMAL);

/**
 * Implements hook_permission().
 */
function zoomapi_permission() {
  return [
    'administer zoomapi' => [
      'title' => t('Administer Zoom API'),
      'description' => t('Administer the Zoom API settings.'),
      'restrict access' => TRUE,
    ],
  ];
}

/**
 * Implements hook_menu().
 */
function zoomapi_menu() {

  // Webhook.
  $items['zoomapi/webhook'] = [
    'title' => 'Zoom API Webhook',
    'description' => 'See https://zoom.github.io/api/#webhooks',
    'page callback' => 'zoomapi_webhooks_callback',
    'access callback' => 'zoomapi_webhooks_access',
    'file' => 'zoomapi.pages.inc',
    'type' => MENU_CALLBACK,
  ];

  // Admin settings.
  $items['admin/config/services/zoomapi'] = [
    'title' => 'Zoom API Settings',
    'description' => 'Configuration for Zoom API',
    'page callback' => 'drupal_get_form',
    'page arguments' => [
      'zoomapi_settings_form',
    ],
    'access arguments' => [
      'administer zoomapi',
    ],
    'file' => 'zoomapi.admin.inc',
    'type' => MENU_NORMAL_ITEM,
  ];
  return $items;
}

/**
 * Access callback: Zoom API Webhooks.
 */
function zoomapi_webhooks_access() {

  // Only allow POST requests.
  $http_verb = strtoupper($_SERVER['REQUEST_METHOD']);
  if ($http_verb != 'POST') {
    return FALSE;
  }

  // Webhooks not enabled.
  if (!variable_get('zoomapi_webhooks_enabled', FALSE)) {
    return FALSE;
  }

  // Validate basic auth.
  if (!empty($_SERVER['PHP_AUTH_USER']) && !empty($_SERVER['PHP_AUTH_PW']) && $_SERVER['PHP_AUTH_USER'] == variable_get('zoomapi_webhooks_username', FALSE) && $_SERVER['PHP_AUTH_PW'] == variable_get('zoomapi_webhooks_password', FALSE)) {
    return TRUE;
  }
  return FALSE;
}

/**
 * Implements hook_cron().
 */
function zoomapi_cron() {
  db_delete('zoomapi_meeting_tracker')
    ->condition('expires', time(), '<=')
    ->execute();
}

/**
 * Get account zoom user ID.
 *
 * @param object $account
 *   The Drupal user account.
 *
 * @return string
 *   The zoom user ID.
 */
function zoomapi_get_zoom_user_id($account) {
  return !empty($account->data['zoomapi_user_id']) ? $account->data['zoomapi_user_id'] : '';
}

/**
 * Get account zoom user email.
 *
 * @param object $account
 *   The Drupal user account.
 *
 * @return string
 *   The zoom user email.
 */
function zoomapi_get_zoom_user_email($account) {
  return !empty($account->data['zoomapi_user_email']) ? $account->data['zoomapi_user_email'] : '';
}

/**
 * Does Zoom user exist for account.
 *
 * @param object $account
 *   The Drupal user account to check if matching Zoom API account exists.
 *
 * @return bool
 *   TRUE if Zoom user account exists for $account, FALSE otherwise.
 */
function zoomapi_user_checkemail($account) {
  if (empty($account->data['zoomapi_user_email'])) {
    return FALSE;
  }
  $zoomapi_user = new ZoomAPIUser();
  return $zoomapi_user
    ->checkemail($account->date['zoomapi_user_email']);
}

/**
 * Find Zoom user by email.
 *
 * The Zoom API does offer an endpoint to search by email, however login_type
 * must be known. This function attempts to work around that by getting a list
 * of all users and searching for the email address.
 *
 * @param string $email
 *   The email address to search for.
 * @param int $page_size
 *   The total number of records to retrieve.
 *
 * @return array
 *   The Zoom user information.
 */
function zoomapi_user_find_by_email($email, $page_size = 100) {
  $zoomapi_user = new ZoomAPIUser();
  $list['page_number'] = 0;
  do {
    $list = $zoomapi_user
      ->list($page_size, $list['page_number'] + 1);
    if (empty($list['users'])) {
      break;
    }
    foreach ($list['users'] as $delta => $zoom_user) {
      if ($zoom_user['email'] == $email) {
        return $zoom_user;
      }
    }
  } while ($list['page_number'] < $list['page_count']);
  return [];
}

/**
 * Connect account with zoom account.
 *
 * There may be cases where a user account exists but the zoomapi_user_id is
 * not set on the Drupal user account data property. This function attempts to
 * check if a zoom user account exists that would link to this user account and
 * update the data properties.
 *
 * @param object $account
 *   The Drupal user account to check if matching Zoom API account exists.
 *
 * @todo
 */
function zoomapi_user_connect_accounts($account) {
  if (!empty($account->data['zoomapi_user_id'])) {
    return TRUE;
  }
}

/**
 * Get Zoom User.
 *
 * @param object $account
 *   The Drupal user account to check if matching Zoom API account exists.
 *
 * @return array
 *   An array of the Zoom user account information.
 */
function zoomapi_user_get($account) {
  if (empty($account->data['zoomapi_user_id'])) {
    return [];
  }
  $zoomapi_user = new ZoomAPIUser();
  $zoom_user = $zoomapi_user
    ->get($account->data['zoomapi_user_id']);

  // If we're unable to retrieve the user using the zoomapi_user_id on the
  // account then it's possible the user account was deleted directly on Zoom.
  // First search by email and update the data properties or remove the data
  // properties from the user.
  if (empty($zoom_user)) {

    // Zoom account found by email so update id.
    if ($zoom_user = zoomapi_user_find_by_email($account->data['zoomapi_user_email'])) {
      $account->data['zoomapi_user_id'] = $zoom_user['id'];
      user_save($account);
    }
    else {
      zoomapi_user_clean_account($account);
    }
  }
  return $zoom_user;
}

/**
 * Create Zoom User.
 *
 * Create a user account on Zoom for a given Drupal user account if the zoom
 * user ID is not already attached to the Drupal user account.
 *
 * @param object $account
 *   The Drupal user account to generate the Zoom account for.
 * @param array $options
 *   Optional array of Zoom user configuration options.
 *
 * @return array
 *   An array of the Zoom user account information.
 */
function zoomapi_user_create($account, array $options = []) {
  $zoomapi_user = new ZoomAPIUser();
  $email = !empty($options['email']) ? $options['email'] : $account->mail;
  $type = !empty($options['type']) ? $options['type'] : variable_get('zoomapi_user_type_default', ZOOMAPI_USER_TYPE_DEFAULT);

  // The 'track_id' on the zoom user will be used to track the Drupal user ID.
  $options['track_id'] = $account->uid;
  if (empty($account->data['zoomapi_user_id']) && ($zoom_user = $zoomapi_user
    ->create($email, $type, $options))) {
    $account->data['zoomapi_user_id'] = $zoom_user['id'];
    $account->data['zoomapi_user_email'] = $zoom_user['email'];
    user_save($account);
    return $zoom_user;
  }
  return [];
}

/**
 * Create Custom Zoom User.
 *
 * Zoom custom accounts are accounts without a password. They are unable to log
 * into the Zoom app or website. These are typically used to generate accounts
 * used to host meetings. Users that use the meeting start url are automatically
 * logged in as the host (custom) account.
 *
 * Given that emails must still be unique, a fake email address is generated
 * based on the account.
 *
 * @param object $account
 *   The Drupal user account to generate the Zoom account for.
 * @param array $options
 *   Optional array of Zoom user configuration options.
 *
 * @return array
 *   An array of the Zoom user account information.
 */
function zoomapi_user_custcreate($account, array $options = []) {
  $zoomapi_user = new ZoomAPIUser();
  $email = !empty($options['email']) ? $options['email'] : zoomapi_user_custcreate_email_generate($account);
  $type = !empty($options['type']) ? $options['type'] : variable_get('zoomapi_user_type_default', ZOOMAPI_USER_TYPE_DEFAULT);

  // The 'track_id' on the zoom user will be used to track the Drupal user ID.
  $options['track_id'] = $account->uid;
  if (empty($account->data['zoomapi_user_id']) && ($zoom_user = $zoomapi_user
    ->custcreate($email, $type, $options))) {
    $account->data['zoomapi_user_id'] = $zoom_user['id'];
    $account->data['zoomapi_user_email'] = $zoom_user['email'];
    user_save($account);
    return $zoom_user;
  }
  return [];
}

/**
 * Update User Info.
 *
 * @param object $account
 *   The Drupal user account to generate the Zoom account for.
 * @param array $options
 *   Optional array of Zoom user configuration options.
 *
 * @return array
 *   An array of the Zoom user account information.
 */
function zoomapi_user_update_info($account, array $options) {

  // In some cases an outdated account is passed without the zoom_user_id. If it
  // doesn't exist then try reloading the account.
  if (empty($account->data['zoomapi_user_id'])) {
    $account = user_load($account->uid);
  }
  if (empty($account->data['zoomapi_user_id'])) {
    watchdog(__FUNCTION__, 'Unable to update account (uid: !uid) due to missing zoom_user_id', [
      '!uid' => $account->uid,
    ], WATCHDOG_ERROR);
    return [];
  }
  $zoomapi_user = new ZoomAPIUser();
  $zoom_user = $zoomapi_user
    ->update($account->data['zoomapi_user_id'], $options);
  return $zoom_user;
}

/**
 * Upload picture to Zoom account.
 *
 * Note: The Zoom API docs mention the image file must be jpg/jpeg.
 *
 * @param object $account
 *   The Drupal user account to check if matching Zoom API account exists.
 * @param object $image_file
 *   The Drupal file object.
 *
 * @todo add watchdog.
 * @todo figure out 'multipart/form-data' error.
 */
function zoomapi_user_uploadpicture($account, $image_file = NULL) {
  if (TRUE) {

    // Figure out @todo error.
    return;
  }
  if (empty($account->data['zoomapi_user_id'])) {
    return;
  }
  if (!$image_file) {
    if (empty($account->picture)) {
      return;
    }
    $image_file = $account->picture;
  }
  if ($image_file->filemime != 'image/jpeg') {
    return;
  }
  $image_url = file_create_url($image_file->uri);
  $zoomapi_user = new ZoomAPIUser();
  $zoomapi_user
    ->uploadpicture($account->data['zoomapi_user_id'], $image_url);
}

/**
 * Generate custom email address for custcreate.
 *
 * @param object $account
 *   The drupal user account to base the custom email from.
 *
 * @return string
 *   The generated email address.
 *
 * @todo document alter hook.
 */
function zoomapi_user_custcreate_email_generate($account) {
  global $base_url;
  $parts = parse_url($base_url);
  $email = "user{$account->uid}@{$parts['host']}";
  $context = [
    'account' => $account,
  ];
  drupal_alter('zoomapi_user_custcreate_email', $email, $context);
  return $email;
}

/**
 * Join Meeting.
 *
 * @param array $meeting
 *   The meeting array returned from the create meeting functions.
 */
function zoomapi_meeting_join(array $meeting) {
  global $user;

  // Ensure we have the latest account information in case the zoomapi_user_id
  // was recently created.
  $account = user_load($user->uid);
  if (!empty($account->data['zoomapi_user_id']) && $account->data['zoomapi_user_id'] == $meeting['host_id']) {
    $url = $meeting['start_url'];
  }
  else {
    $url = $meeting['join_url'];
  }
  watchdog(__FUNCTION__, 'User @name (uid: !uid) joined meeting "@topic" (id: !meeting_id).', [
    '@name' => $account->name,
    '!uid' => $account->uid,
    '@topic' => $meeting['topic'],
    '!meeting_id' => $meeting['id'],
  ], WATCHDOG_INFO);
  drupal_goto($url, [
    'external' => TRUE,
  ]);
}

/**
 * Create Meeting.
 *
 * @param object $account
 *   The Drupal account to act as the host.
 * @param array $options
 *   Optional array of meeting options.
 *
 * @return array
 *   An array of the meeting setup.
 *
 * @todo add meeting tracking for easier start/join url lookups for live
 * meetings.
 */
function zoomapi_meeting_create($account, array $options = []) {
  if (empty($account->data['zoomapi_user_id'])) {
    return [];
  }
  if (empty($options['type'])) {
    $options['type'] = variable_get('zoomapi_meeting_type_default', ZOOMAPI_MEETING_TYPE_DEFAULT);
  }
  if (empty($options['topic'])) {
    $options['topic'] = zoomapi_meeting_topic_generate($account, $options);
  }
  $zoomapi_meeting = new ZoomAPIMeeting();
  $zoom_meeting = $zoomapi_meeting
    ->create($account->data['zoomapi_user_id'], $options['topic'], $options['type'], $options);
  zoomapi_track_meeting($zoom_meeting);
  return $zoom_meeting;
}

/**
 * Create Meeting for Entity.
 *
 * Create a meeting for a specific Drupal entity (node). The typical use case is
 * an Event content type (node) or entity.
 *
 * @param object $account
 *   The Drupal account to act as the host.
 * @param object $entity
 *   The entity the meeting is being created for.
 * @param string $entity_type
 *   The type (node, user, etc.) of entity.
 * @param array $options
 *   Optional array of meeting options.
 *
 * @return array
 *   An array of the meeting setup.
 *
 * @todo add meeting tracking for easier start/join url lookups for live
 * meetings.
 */
function zoomapi_meeting_create_for_entity($account, $entity, $entity_type, array $options = []) {
  if (empty($account->data['zoomapi_user_id'])) {
    return [];
  }
  if (empty($options['type'])) {
    $options['type'] = variable_get('zoomapi_meeting_type_default', ZOOMAPI_MEETING_TYPE_DEFAULT);
  }
  if (empty($options['topic'])) {
    $options['topic'] = zoomapi_meeting_topic_generate_for_entity($account, $entity, $entity_type, $options);
  }
  list($entity_id, $revision_id, $bundle) = entity_extract_ids($entity_type, $entity);
  $zoomapi_meeting = new ZoomAPIMeeting();
  $zoom_meeting = $zoomapi_meeting
    ->create($account->data['zoomapi_user_id'], $options['topic'], $options['type'], $options);
  $zoom_meeting['entity_type'] = $entity_type;
  $zoom_meeting['entity_id'] = $entity_id;
  zoomapi_track_meeting($zoom_meeting);
  return $zoom_meeting;
}

/**
 * Get Meeting for Entity.
 *
 * @param object $entity
 *   The entity the meeting is being created for.
 * @param string $entity_type
 *   The type (node, user, etc.) of entity.
 *
 * @return array
 *   An array of the meeting setup.
 */
function zoomapi_meeting_get_meeting_for_entity($entity, $entity_type) {
  list($entity_id, $revision_id, $bundle) = entity_extract_ids($entity_type, $entity);
  $sql = 'SELECT data FROM {zoomapi_meeting_tracker}';
  $sql .= ' WHERE entity_type = :entity_type';
  $sql .= ' AND entity_id = :entity_id';

  // We only expect a single record for any entity_type/entity_id. Just in case
  // that is a false assumption, sort by the created date DESC so we grab the
  // most recent record.
  $sql .= ' ORDER BY created DESC';
  $sql_args = [
    ':entity_type' => $entity_type,
    ':entity_id' => $entity_id,
  ];
  if ($data = db_query($sql, $sql_args)
    ->fetchField()) {
    return unserialize($data);
  }
  return [];
}

/**
 * Create Instant Meeting for Account.
 *
 * @param object $account
 *   The Drupal account to act as the host.
 * @param array $options
 *   Optional array of meeting options.
 *
 * @return array
 *   An array of the meeting setup.
 */
function zoomapi_meeting_create_instant_meeting($account, array $options = []) {
  if (empty($account->data['zoomapi_user_id'])) {
    return [];
  }
  $options['type'] = ZOOMAPI_MEETING_TYPE_INSTANT;
  if (empty($options['topic'])) {
    $options['topic'] = zoomapi_meeting_topic_generate_for_entity($account, $account, 'user', $options);
  }
  $zoom_meeting = zoomapi_meeting_create_for_entity($account, $account, 'user', $options);
  $zoom_meeting['entity_type'] = 'user';
  $zoom_meeting['entity_id'] = $account->uid;
  zoomapi_track_meeting($zoom_meeting);
  return $zoom_meeting;
}

/**
 * Get account instant meeting information.
 *
 * @param object $account
 *   The Drupal account to act as the host.
 *
 * @return array
 *   The meeting information.
 */
function zoomapi_meeting_get_account_instant_meeting($account) {
  if (empty($account->data['zoomapi_user_id'])) {
    return [];
  }
  $sql = 'SELECT data FROM {zoomapi_meeting_tracker}';
  $sql .= ' WHERE host_zoom_user_id = :host_id';
  $sql .= ' AND meeting_type = :instant';
  $sql_args = [
    ':host_id' => $account->data['zoomapi_user_id'],
    ':instant' => ZOOMAPI_MEETING_TYPE_INSTANT,
  ];
  if ($data = db_query($sql, $sql_args)
    ->fetchField()) {
    return unserialize($data);
  }
  return [];
}

/**
 * Generate topic for a Zoom meeting.
 *
 * @param object $account
 *   The drupal account acting as meeting host.
 * @param array $options
 *   Optional array of meeting options.
 *
 * @return string
 *   The meeting topic.
 *
 * @todo add drupal_alter hook.
 */
function zoomapi_meeting_topic_generate($account, array $options = []) {
  $topic = t('Meeting for @name', [
    '@name' => $account->name,
  ]);
  $context = [
    'account' => $account,
    'options' => $options,
  ];
  drupal_alter('zoomapi_meeting_topic', $topic, $context);
  return $topic;
}

/**
 * Generate topic for a entity-based Zoom meeting.
 *
 * @param object $account
 *   The drupal account acting as meeting host.
 * @param object $entity
 *   The entity the meeting is being created for.
 * @param string $entity_type
 *   The type (node, user, etc.) of entity.
 * @param array $options
 *   Optional array of meeting options.
 *
 * @return string
 *   The meeting topic.
 *
 * @todo add drupal_alter hook.
 */
function zoomapi_meeting_topic_generate_for_entity($account, $entity, $entity_type, array $options = []) {
  $entity_wrapper = entity_metadata_wrapper($entity_type, $entity);
  $topic = $entity_wrapper
    ->label();
  $context = [
    'account' => $account,
    'entity' => $entity,
    'entity_type' => $entity_type,
    'options' => $options,
  ];
  drupal_alter('zoomapi_meeting_topic_for_entity', $topic, $context);
  if (empty($topic)) {
    $topic = zoomapi_meeting_topic_generate($account);
  }
  return $topic;
}

/**
 * Track meeting information.
 *
 * @param array $meeting
 *   The meeting array provided by Zoom.
 */
function zoomapi_track_meeting(array $meeting) {
  $record = [
    'uuid' => $meeting['uuid'],
    'meeting_id' => $meeting['id'],
    'host_zoom_user_id' => $meeting['host_id'],
    'topic' => $meeting['topic'],
    'meeting_type' => $meeting['type'],
    'start_time' => !empty($meeting['start_time']) ? strtotime($meeting['start_time']) : 0,
    'duration' => !empty($meeting['duration']) ? $meeting['duration'] : 0,
    'timezone' => !empty($meeting['timezone']) ? $meeting['timezone'] : '',
    'start_url' => $meeting['start_url'],
    'join_url' => $meeting['join_url'],
    'created' => time(),
    'entity_type' => !empty($meeting['entity_type']) ? $meeting['entity_type'] : '',
    'entity_id' => !empty($meeting['entity_id']) ? $meeting['entity_id'] : 0,
    // Default record expires after 24 hrs.
    'expires' => strtotime('+24 hours'),
    'data' => serialize($meeting),
  ];

  // If the start time and duration is found, then expire the record several
  // hours after the meeting is set to end.
  if (!empty($record['start_time']) && !empty($record['duration'])) {
    $record['expires'] = $record['start_time'] + $record['duration'] + 2 * 60 * 60;
  }

  // There should not be multiple instant meetings for the same host account.
  // While not performing a logic check here to stop that, we do want to at
  // least eliminate any existing instant records for that host. This will avoid
  // any potential look ups later to find an account's instant meeting.
  if ($record['meeting_type'] == ZOOMAPI_MEETING_TYPE_INSTANT) {
    $num_deleted = db_delete('zoomapi_meeting_tracker')
      ->condition('host_zoom_user_id', $record['host_zoom_user_id'])
      ->condition('meeting_type', ZOOMAPI_MEETING_TYPE_INSTANT)
      ->execute();
    if ($num_deleted && variable_get('zoomapi_debug', FALSE)) {
      watchdog('zoomapi_debug', 'Removed !count existing instant meeting tracker for host_id !host_id', [
        '!count' => $num_deleted,
        '!host_id' => $record['host_zoom_user_id'],
      ], WATCHDOG_DEBUG);
    }
  }

  // There should only be one meeting per entity_type/entity_id. While not
  // performing logic check here, at least make sure table only has one record.
  if (!empty($record['entity_type']) && !empty($record['entity_id'])) {

    // At this time do not delete the record and instead check to see if one
    // already exists.
    if (variable_get('zoomapi_debug', FALSE)) {
      $count = db_query('SELECT count(uuid) FROM {zoomapi_meeting_tracker} WHERE entity_type = :entity_type AND entity_id = :entity_id', [
        ':entity_type' => $record['entity_type'],
        ':entity_id' => $record['entity_id'],
      ])
        ->rowCount();
      if ($count) {
        watchdog('zoomapi_debug', '!count zoomapi_meeting_tracker records already exist for entity_type !entity_type entity_id !entity_id', [
          '!count' => $count,
          '!entity_type' => $record['entity_type'],
          '!entity_id' => $record['entity_id'],
        ], WATCHDOG_DEBUG);
      }
    }

    // @todo
    // Do we need to do this?
    if (FALSE) {
      db_delete('zoomapi_meeting_tracker')
        ->condition('entity_type', $record['entity_type'])
        ->condition('entity_id', $record['entity_id'])
        ->execute();
    }
  }
  db_merge('zoomapi_meeting_tracker')
    ->key([
    'uuid' => $record['uuid'],
  ])
    ->fields($record)
    ->execute();
}

/**
 * Get account cloud recordings.
 *
 * @param object $account
 *   The user account to retrieve the cloud recordings for.
 * @param array $options
 *   An optional array of options to filter the recordings list.
 *
 * @see ZoomAPIRecording->list()
 */
function zoomapi_recordings_get_list($account, array $options = []) {
  $account_recordings = [];
  if ($host_zoom_user_id = zoomapi_get_zoom_user_id($account)) {
    $zoomapi_recordings = new ZoomAPIRecording();

    // @todo utilize $options.
    $account_recordings = $zoomapi_recordings
      ->list($host_zoom_user_id);
  }
  return $account_recordings;
}

/**
 * Clean Drupal account of zoom api elements.
 *
 * @param object $account
 *   The drupal account to clean.
 */
function zoomapi_user_clean_account($account) {
  unset($account->data['zoomapi_user_id']);
  unset($account->data['zoomapi_user_email']);
  user_save($account);
}

Functions

Namesort descending Description
zoomapi_cron Implements hook_cron().
zoomapi_get_zoom_user_email Get account zoom user email.
zoomapi_get_zoom_user_id Get account zoom user ID.
zoomapi_meeting_create Create Meeting.
zoomapi_meeting_create_for_entity Create Meeting for Entity.
zoomapi_meeting_create_instant_meeting Create Instant Meeting for Account.
zoomapi_meeting_get_account_instant_meeting Get account instant meeting information.
zoomapi_meeting_get_meeting_for_entity Get Meeting for Entity.
zoomapi_meeting_join Join Meeting.
zoomapi_meeting_topic_generate Generate topic for a Zoom meeting.
zoomapi_meeting_topic_generate_for_entity Generate topic for a entity-based Zoom meeting.
zoomapi_menu Implements hook_menu().
zoomapi_permission Implements hook_permission().
zoomapi_recordings_get_list Get account cloud recordings.
zoomapi_track_meeting Track meeting information.
zoomapi_user_checkemail Does Zoom user exist for account.
zoomapi_user_clean_account Clean Drupal account of zoom api elements.
zoomapi_user_connect_accounts Connect account with zoom account.
zoomapi_user_create Create Zoom User.
zoomapi_user_custcreate Create Custom Zoom User.
zoomapi_user_custcreate_email_generate Generate custom email address for custcreate.
zoomapi_user_find_by_email Find Zoom user by email.
zoomapi_user_get Get Zoom User.
zoomapi_user_update_info Update User Info.
zoomapi_user_uploadpicture Upload picture to Zoom account.
zoomapi_webhooks_access Access callback: Zoom API Webhooks.

Constants