How to use longSleep method in Appium Android Driver

Best JavaScript code snippet using appium-android-driver

kwm.js

Source:kwm.js Github

copy

Full Screen

1import { defineMessages } from 'react-intl';2import { setError, enqueueErrorSnackbar, enqueueSnackbar, closeSnackbar } from 'kpop/es/common/actions';3import * as kwmjs from 'kwmjs';4import adapter from 'webrtc-adapter';5import * as types from './types';6import * as errors from '../errors';7import * as sdputils from '../sdputils';8import { fetchAndUpdateContactByID } from './contacts';9import { resolveContactIDFromRecord } from '../utils';10import { guestLogon } from '../api/kwm';11console.info(`Kopano KWM js version: ${kwmjs.version}`); // eslint-disable-line no-console12const defaultAudioVideoSdpParams = {13  videoRecvCodec: 'VP8', // Prefer VP8 since it takes less CPU?14  videoSendBitrate: 1000, // kbps15  videoRecvBitrate: 1000, // kbps16};17const defaultAudioVideoLocalParams = {18  opusDtx: true,19  opusFec: true,20  opusMaxPbr: 48000, // nb: 8, mb: 12, wb: 16, swb: 24, fb: 48 (all kHz)21};22const defaultAudioVideoRemoteParams = {};23const defaultScreenhareSdpParams = {24  videoRecvCodec: 'VP9', // Prefer VP9 since its more modern and gives better results for screen sharing.25  videoSendBitrate: 2500, // kbps26  videoRecvBitrate: 2500, // kbps27};28// Fixup webrtc-adpter for Firefox to be compatible with kwmjs simple-peer poor feature detection.29// See https://github.com/feross/simple-peer/commits/master/index.js and ensure it ends up to detect promise based shit.30(() => {31  if (adapter.browserDetails.browser === 'firefox') {32    // Ensure that function signature of getStats has zero parameters, so that33    // the feature detection of kwmks simple-peer does select the promise based34    // mode.35    if (window.RTCPeerConnection.prototype.getStats.length > 0) {36      const adaptedGetStats = window.RTCPeerConnection.prototype.getStats;37      window.RTCPeerConnection.prototype.getStats = function() {38        return adaptedGetStats.apply(this);39      };40    }41  }42})();43// Reference to the active KWM and options.44let kwm = null;45const kwmOptions = {46  id: null,47  user: null,48  userMode: 'id_token',49  options: {},50};51// KWM config.52const kwmConfig = (() => {53  const config ={54    url: '',55    webrtc: {},56    sdpParams: {},57  };58  return config;59})();60const translations = defineMessages({61  kwmError: {62    id: 'kwm.errorMessage.kwmError.message',63    defaultMessage: 'Error: KWM error - {msg} {code}',64  },65});66// Default WebRTC constraints.67const defaultCommonConstraints = (() => {68  const constraints = {};69  if (adapter.browserDetails.browser === 'chrome') {70    // Add Google specific constraints.71    Object.assign(constraints, {72      googIPv6: true, // Constraint to enable IPv6 through JS.73      googDscp: true, // Temporary pseudo-constraint for enabling DSCP through JS.74      // Google specific constraints.75      googCpuOveruseDetection: true,76      googCpuOveruseEncodeUsage: true,77      googCpuUnderuseThreshold: 55,78      googCpuOveruseThreshold: 85,79      googHighStartBitrate: 0,80      googPayloadPadding: true,81      googSuspendBelowMinBitrate: true,82      googScreencastMinBitrate: 400,83    });84  }85  return constraints;86})();87// WebRTC confg.88const webrtcConfig = (() => {89  const config = {90    iceServers: [91      {urls: 'stun:stun.kopano.com:443'},92    ],93    iceTransportPolicy: 'all', // Either 'all' or 'relay' to force going through relay.94  };95  if (adapter.browserDetails.browser === 'chrome') {96    // For interoperability with Firefox and others, we need to send standard sdp. This sets the plan to unified plan97    // effectively breaking compatibilty with Chromeium < M69. See https://webrtc.org/web-apis/chrome/unified-plan/.98    config.sdpSemantics = 'unified-plan';99  }100  return config;101})();102// WebRTC options.103const webrtcOptions = {104  answerConstraints: {105    ...defaultCommonConstraints,106  },107  offerConstraints: {108    ...defaultCommonConstraints,109  },110};111// SDP Config.112const sdpParamsAudioVideo = {113  ...defaultAudioVideoSdpParams,114};115const sdpParamsScreenshare = {116  ...defaultScreenhareSdpParams,117};118export function setupKWM(id, idToken, {authorizationType, authorizationValue, autoConnect, eventCallback} = {}) {119  return async (dispatch, getState) => {120    const { config } = getState().common;121    if (id !== kwmOptions.id) {122      // Always disconnect when the user changed.123      await dispatch(disconnectFromKWM());124    }125    // Update KWM options by reference.126    kwmOptions.id = id; // eslint-disable-line require-atomic-updates127    kwmOptions.user = idToken; // eslint-disable-line require-atomic-updates128    Object.assign(kwmOptions.options, {129      authorizationType,130      authorizationValue,131      authorizationAuth: config.useIdentifiedUser ? '1' : '', // Use auth 1 to use real user identity.132    });133    // Auto connect support when requested.134    if (autoConnect) {135      if (kwm && kwm.connected) {136        return kwm;137      }138      return dispatch(connectToKWM(idToken, eventCallback));139    }140    return kwm;141  };142}143export function destroyKWM() {144  return async (dispatch) => {145    if (kwm) {146      await dispatch(disconnectFromKWM());147      kwm = null; // eslint-disable-line require-atomic-updates148    }149  };150}151function connectToKWM(user, eventCallback) {152  return async (dispatch) => {153    if (!user || kwmOptions.user !== user) {154      throw new Error('invalid user set for KWM connect');155    }156    if (!kwmOptions.options.authorizationType) {157      throw new Error('no user or options set for KWM connect');158    }159    if (kwm === null) {160      kwm = await dispatch(createKWMManager(eventCallback)); // eslint-disable-line require-atomic-updates161    }162    await kwm.connect(user, kwmOptions.userMode);163    return kwm;164  };165}166function disconnectFromKWM() {167  return async () => {168    if (kwm) {169      try {170        await kwm.destroy();171      } catch(err) {172        console.error('disconnect destroy failed with error', err); // eslint-disable-line no-console173      }174    }175    kwmOptions.id = null;176    kwmOptions.user = null;177    delete kwmOptions.options.authorizationType;178    delete kwmOptions.options.authorizationValue;179  };180}181function createKWMManager(eventCallback) {182  return async (dispatch, getState) => {183    const { config } = getState().common;184    const { mode } = getState().meet;185    if (!config.kwm) {186      throw new Error('config is missing KWM configuration data');187    }188    // Update defaults from configuration.189    Object.assign(kwmConfig, config.kwm);190    Object.assign(webrtcConfig, kwmConfig.webrtc.config);191    Object.assign(webrtcOptions, kwmConfig.webrtc.options);192    Object.assign(sdpParamsAudioVideo, kwmConfig.sdpParams);193    Object.assign(sdpParamsScreenshare, kwmConfig.sdpParamsScreenshare);194    kwmjs.KWMInit.init({}); // Init with default options.195    const k = new kwmjs.KWM(kwmConfig.url, kwmOptions.options);196    k.webrtc.config = {197      ...webrtcConfig,198    };199    k.webrtc.options = {200      ...webrtcOptions,201      localSDPTransform: (sdp, kind='') => {202        const { settings } = getState().media;203        let sdpParams;204        switch (kind) {205          case 'screenshare':206            sdpParams = sdpParamsScreenshare;207            break;208          default:209            sdpParams = sdpParamsAudioVideo;210            break;211        }212        // Local SDP transform support.213        const params = Object.assign({214          ...defaultAudioVideoLocalParams,215        }, sdpParams, {216          // TODO(longsleep): Add configuration settings here.217          opusStereo: true, // Tell the receiver to decode stereo.218          opusSpropStereo: settings.audio.channelCount === 2,219        });220        sdp = sdputils.maybeSetOpusOptions(sdp, params);221        sdp = sdputils.maybePreferAudioReceiveCodec(sdp, params);222        sdp = sdputils.maybePreferVideoReceiveCodec(sdp, params);223        sdp = sdputils.maybeSetAudioReceiveBitRate(sdp, params);224        sdp = sdputils.maybeSetVideoReceiveBitRate(sdp, params);225        sdp = sdputils.maybeRemoveVideoFec(sdp, params);226        return sdp;227      },228      remoteSDPTransform: (sdp, kind='') => {229        let sdpParams;230        switch (kind) {231          case 'screenshare':232            sdpParams = sdpParamsScreenshare;233            break;234          default:235            sdpParams = sdpParamsAudioVideo;236            break;237        }238        // Remote SDP transform support.239        const params = Object.assign({240          ...defaultAudioVideoRemoteParams,241        }, sdpParams, {242          // TODO(longsleep): Add configuration settings here.243        });244        sdp = sdputils.maybeSetOpusOptions(sdp, params);245        sdp = sdputils.maybePreferAudioSendCodec(sdp, params);246        sdp = sdputils.maybePreferVideoSendCodec(sdp, params);247        sdp = sdputils.maybeSetAudioSendBitRate(sdp, params);248        sdp = sdputils.maybeSetVideoSendBitRate(sdp, params);249        sdp = sdputils.maybeSetVideoSendInitialBitRate(sdp, params);250        sdp = sdputils.maybeRemoveVideoFec(sdp, params);251        return sdp;252      },253      transceiverRequestTransform: (transceiverRequest) => {254        if (transceiverRequest && transceiverRequest.kind === 'video') {255          const { mode } = getState().meet;256          if (mode === 'call') {257            // Do not create receiver for video track if in call mode. This258            // is the way how receiving of unwanted streams is prevented if we259            // are the offerer.260            return null;261          }262        }263        return transceiverRequest;264      },265      onRemoteDescriptionSet: (owner, pc) => {266        if (pc.remoteDescription.type === 'offer') {267          // If remote is the offerer, we can further control incoming transceivers268          // base based on our local state, before we send back the answer.269          const { mode } = getState().meet;270          // Do not accept video receiversx if in call mode.271          pc.getTransceivers().forEach(transceiver => {272            if (transceiver.receiver && transceiver.receiver.track && transceiver.receiver.track.kind === 'video') {273              if (mode === 'call') {274                transceiver.direction = 'inactive';275              } else if (transceiver.direction === 'inactive') {276                // Resurrect, to be able to receive again.277                transceiver.direction = 'sendrecv';278              }279            }280          });281        }282      },283    };284    console.info('KWM init', kwmConfig, webrtcConfig, webrtcOptions, sdpParamsAudioVideo, sdpParamsScreenshare); // eslint-disable-line no-console285    let connected = undefined;286    k.onstatechanged = event => {287      if (event.target !== kwm) {288        return;289      }290      if (event.connected) {291        // Ensure that all existing pc connections do a renegotiation dance after292        // kwm server connection to ensure server state is correct.293        kwm.webrtc.peers.forEach(record => {294          if (record.pc) {295            record.pc._needsNegotiation();296          }297        });298      }299      if (connected === undefined) {300        connected = event.connected;301        if (!event.connected) {302          // NOTE(longsleep): Ignore initial unconnected state.303          return;304        }305      }306      dispatch(stateChanged(event));307    };308    k.onserverstatus = event => {309      if (event.target !== kwm) {310        return;311      }312      console.info('KWM server status update', event.serverStatus); // eslint-disable-line no-console313      dispatch(serverStatus(event));314    };315    k.onerror = event => {316      if (event.target !== kwm) {317        return;318      }319      dispatch(error(event));320    };321    k.onturnserverchanged = event => {322      console.info('KWM using TURN servers', event.iceServer.urls); // eslint-disable-line no-console323    };324    k.webrtc.onpeer = event => {325      if (!kwm || event.target !== kwm.webrtc) {326        return;327      }328      switch (event.event) {329        case 'newcall':330          dispatch(newCall(event));331          break;332        case 'destroycall':333          dispatch(destroyAndHangupCall(event));334          break;335        case 'abortcall':336          dispatch(abortAndHangupCall(event));337          break;338        case 'incomingcall':339          dispatch(incomingCall(event));340          break;341        case 'outgoingcall':342          dispatch(outgoingCall(event));343          break;344        case 'pc.connect':345          dispatch(pcConnect(event));346          break;347        case 'pc.closed':348          dispatch(pcClosed(event));349          break;350        case 'pc.iceStateChange':351          // TODO(longsleep): Implement iceRestart.352          // See https://github.com/w3c/webrtc-pc/pull/1910#issuecomment-398986406353          // and https://w3c.github.io/webrtc-pc/#dom-rtcofferoptions-icerestart.354          break;355        // Reduce logging.356        case 'pc.new':357        case 'pc.signalingStateChange':358        case 'pc.error':359        case 'hangup':360          //console.debug(`KWM event ${event.event}`, event.details, event.record);361          break;362        // Catch unknowns.363        default:364          console.warn('KWM unknown peer event', event.event, event); // eslint-disable-line no-console365          break;366      }367      // Cleanup if no peers are left.368      if (event.target.peers.size === 0) {369        if (event.target.channel !== '' && !event.target.group) {370          console.log('KWM hangup as no peers are left'); // eslint-disable-line no-console371          dispatch(doHangup());372        } else if (event.target.channel === '') {373          // Reset channel when not having a channel and no peers.374          dispatch(resetChannel());375        }376      }377      if (eventCallback) {378        eventCallback(event);379      }380    };381    k.webrtc.onannouncestreams = event => {382      if (!kwm || event.target !== kwm.webrtc) {383        return;384      }385      dispatch(streamsAnnounce(event));386    };387    k.webrtc.ontrack = event => {388      if (!kwm || event.target !== kwm.webrtc) {389        return;390      }391      dispatch(streamReceived(event));392    };393    k.chats.onmessage = event => {394      if (!kwm || event.target !== kwm.chats) {395        return;396      }397      // Ensure to let through only message kinds we know about.398      const { message } = event;399      switch (message.kind) {400        case '':401          break;402        default:403          console.warn('unknown chats message kind received', message.kind); // eslint-disable-line no-console404          return;405      }406      dispatch(chatsMessageReceived(event));407    };408    k.chats.onsystem = event => {409      if (!kwm || event.target !== kwm.chats) {410        return;411      }412      dispatch(chatsSystemReceived(event));413    };414    k.webrtc.setMode(mode);415    return k;416  };417}418function error(event) {419  return async (dispatch) => {420    let fatal = true;421    switch (event.code) {422      case 'no_session_for_user':423        // NOTE(longsleep): This error is pretty useless as it does not return424        // enough information to know which call actually is meant here.425        console.debug('KMW error ignored', event.code, event); // eslint-disable-line no-console426        return;427      case 'http_error_403':428        // NOTE(longsleep): For whatever reason we were not allowed to429        // connect KWM. Do something useful instead of just bailing430        // with the error since this can happen when the access token431        // is expired (like after a device resume).432        dispatch(doHangup());433        await setNonFatalError(errors.ERROR_KWM_NO_PERMISSION, event);434        return;435      case 'websocket_error':436        // NOTE(longsleep): We ignore websocket errors here. KWM will automatically437        // reconnect.438        console.debug('KWM error ignored', event.code, event); // eslint-disable-line no-console439        return;440      default:441    }442    console.warn('KWM error event', event.code, event); // eslint-disable-line no-console443    // TODO(longsleep): Make only fatal if kwm is not reconnecting.444    const error = {445      message: translations.kwmError,446      fatal: fatal,447      values: {448        msg: event.msg,449        code: event.code,450      },451    };452    dispatch(doHangup());453    await dispatch(setError(error));454  };455}456function stateChanged(event) {457  return (dispatch, getState) => {458    const { connected: oldConnected } = getState().kwm;459    const { connecting, connected, reconnecting } = event;460    if (oldConnected !== connected) {461      if (!connected && kwmOptions.id) {462        const error = {463          fatal: false,464          options: {465            key: 'kwm_statechanged_not_connected',466            persist: true,467          },468        };469        error.message = oldConnected ? 'Lost connection to server - check your Internet connection.' : 'Failed to connect to server - check your Internet connection.';470        dispatch(closeSnackbar('kwm_statechanged_connected'));471        dispatch(enqueueErrorSnackbar(error));472      } else if (oldConnected === false) {473        const notification = {474          message: 'Server connection reestablished.',475          options: {476            key: 'kwm_statechanged_connected',477            variant: 'success',478          },479        };480        dispatch(closeSnackbar('kwm_statechanged_not_connected'));481        dispatch(enqueueSnackbar(notification));482      }483    }484    return dispatch({485      type: types.KWM_STATE_CHANGED,486      connecting,487      connected,488      reconnecting,489    });490  };491}492function serverStatus(event) {493  return (dispatch, getState) => {494    const { serverStatus } = event;495    dispatch( {496      type: types.KWM_SERVERSTATUS_CHANGED,497      serverStatus,498    });499  };500}501function channelChanged(channel) {502  return {503    type: types.KWM_CHANNEL_CHANGED,504    channel,505  };506}507function incomingCall(event, doneHandler = null) {508  const { record } = event;509  return {510    type: types.KWM_CALL_INCOMING,511    record,512    doneHandler,513  };514}515function outgoingCall(event, doneHandler = null) {516  const { record } = event;517  return {518    type: types.KWM_CALL_OUTGOING,519    record,520    doneHandler,521  };522}523function newCall(event) {524  const { record } = event;525  return async (dispatch, getState) => {526    const state = getState();527    const { table } = state.contacts;528    const { config } = state.common;529    const id = resolveContactIDFromRecord(config, event.record);530    let entry = table[id];531    if (!entry) {532      console.warn('unknown user for call', event.record.user); // eslint-disable-line no-console533      entry = {534        // TODO(longsleep): Find some way to describe unknown users.535        displayName: '',536      };537      // Try to fetch contact data via api.538      dispatch(fetchAndUpdateContactByID(id)).catch(err => {539        console.warn('failed to fetch and update contact' + // eslint-disable-line no-console540        ' information for new call', err);541      });542    }543    // Copy to retain reference.544    const user = {displayName: entry.displayName};545    return dispatch({546      type: types.KWM_CALL_NEW,547      record,548      user,549    });550  };551}552function destroyCall(event) {553  const { record } = event;554  // TODO(longsleep): Reconnect instead of hangup?555  if (kwm.webrtc.peers.get(record.user)) {556    kwm.webrtc.doHangup(record.user);557  }558  return {559    type: types.KWM_CALL_DESTROY,560    record,561  };562}563function pcConnect(event) {564  const { record, details: pc } = event;565  return {566    type: types.KWM_PC_CONNECT,567    record,568    pc,569  };570}571function pcClosed(event) {572  const { record, details: pc } = event;573  return {574    type: types.KWM_PC_CLOSED,575    record,576    pc,577  };578}579function destroyAndHangupCall(event) {580  const { record } = event;581  return async dispatch => {582    dispatch(destroyCall(event));583    if (kwm.webrtc.peers.get(record.user)) {584      await kwm.webrtc.doHangup(record.user);585    }586  };587}588function abortCall(event) {589  const { record, details } = event;590  return {591    type: types.KWM_CALL_ABORT,592    record,593    details,594  };595}596function abortAndHangupCall(event) {597  const { record } = event;598  return async dispatch => {599    dispatch(abortCall(event));600    if (kwm.webrtc.peers.get(record.user)) {601      await kwm.webrtc.doHangup(record.user);602    }603  };604}605function streamReceived(event) {606  const { record, stream, token } = event;607  return {608    type: types.KWM_STREAM_RECEIVED,609    record,610    stream,611    token,612  };613}614function streamsAnnounce(event) {615  const { record, added, removed } = event;616  return {617    type: types.KWM_STREAMS_ANNOUNCE,618    record,619    added,620    removed,621  };622}623function resetChannel() {624  return async (dispatch, getState) => {625    const { channel } = getState().kwm;626    if (channel) {627      await dispatch(channelChanged(null));628    }629  };630}631function setNonFatalError(text, err) {632  if (err) {633    // TODO(longsleep): Pure man error conversion follows. This needs real634    // messages for the known errors and translation.635    if (err.msg) {636      err = err.msg;637    } else if (err.code) {638      err = (''+err.code).replace('_', ' ');639    }640    text += ' - ' + err;641  }642  return async dispatch => {643    await dispatch(setError({644      message: text,645      fatal: false,646    }));647  };648}649export function doCall(id, errorCallback) {650  return async dispatch => {651    if (!kwm || !kwm.webrtc) {652      throw new Error('no kwm');653    }654    await dispatch({655      type: types.KWM_DO_CALL,656      id,657    });658    return kwm.webrtc.doCall(id).then(channel => {659      console.info('KWM channel create', channel); // eslint-disable-line no-console660      dispatch(channelChanged(channel));661      return channel;662    }).catch(err => {663      dispatch({664        type: types.KWM_CLEAR_CALLING,665        id,666      });667      dispatch(doHangup(id, '')); // Hangup without reason is a local hangup.668      err = errorCallback ? errorCallback(err) : err;669      if (err) {670        console.error('KWM doCall failed', err);  // eslint-disable-line no-console671        dispatch(setNonFatalError(errors.ERROR_KWM_UNABLE_TO_CALL, err));672      }673    });674  };675}676export function doHangup(id='', reason) {677  return async dispatch => {678    // Hangs up all and everyone679    await dispatch({680      type: types.KWM_DO_HANGUP,681      id,682      reason,683    });684    if (!kwm || !kwm.webrtc) {685      return;686    }687    return kwm.webrtc.doHangup(id, reason).then(channel => {688      console.info('KWM channel release', channel); // eslint-disable-line no-console689      dispatch(resetChannel());690    }).catch(err => {691      dispatch(doHangup(id, '')); // Hangup without reason is a local hangup.692      console.error('KWM doHangup failed', err);  // eslint-disable-line no-console693      // FIXME(longsleep): Only hang up locally is probably not ideal - maybe694      // an error message should be shown?695    });696  };697}698export function doGroup(id, errorCallback) {699  return async dispatch => {700    if (!kwm || !kwm.webrtc) {701      throw new Error('no kwm');702    }703    await dispatch({704      type: types.KWM_DO_GROUP,705      id,706    });707    return kwm.webrtc.doGroup(id).then(channel => {708      console.info('KWM group channel create', channel); // eslint-disable-line no-console709      dispatch(channelChanged(channel));710      return channel;711    }).catch(err => {712      err = errorCallback ? errorCallback(err) : err;713      if (err) {714        console.error('KWM doGroup failed', err);  // eslint-disable-line no-console715        dispatch(setNonFatalError(error.ERROR_KWM_UNABLE_TO_JOIN, err));716      }717    });718  };719}720export function doSendChatMessage(channel, message, errorCallback) {721  return async dispatch => {722    if (!kwm || !kwm.chats) {723      throw new Error('no kwm');724    }725    return kwm.chats.doSendChatMessage(channel, message).then(replyMessage => {726      if (replyMessage === undefined) {727        // NOTE(longsleep): undefined happens when kwmserver rejects the message728        // as this case is currently not handled in kwmjs at the moment.729        throw new Error('no reply data');730      }731      return replyMessage;732    }).catch(err => {733      err = errorCallback ? errorCallback(err) : err;734      if (err) {735        console.error('KWM doSendChatMessage failed', err); // eslint-disable-line no-console736        // TODO(longsleep): Dispatch proper error.737      }738      return null;739    });740  };741}742export function doAccept(id) {743  return async dispatch => {744    if (!kwm || !kwm.webrtc) {745      throw new Error('no kwm');746    }747    await dispatch({748      type: types.KWM_DO_ACCEPT,749      id,750    });751    return kwm.webrtc.doAnswer(id).then(channel => {752      console.info('KWM channel create', channel); // eslint-disable-line no-console753      dispatch(channelChanged(channel));754      return channel;755    }).catch(err => {756      console.error('KWM doAccept failed', err);  // eslint-disable-line no-console757      dispatch(setNonFatalError(error.ERROR_KWM_UNABLE_TO_ACCEPT, err));758    });759  };760}761export function doReject(id, reason='reject') {762  return async dispatch => {763    if (!kwm || !kwm.webrtc) {764      throw new Error('no kwm');765    }766    await dispatch({767      type: types.KWM_DO_REJECT,768      id,769      reason,770    });771    return kwm.webrtc.doReject(id, reason).catch(err => {772      console.error('KWM doReject failed', err);  // eslint-disable-line no-console773      dispatch(doHangup(id, '')); // Hangup without reason is a local hangup.774      // FIXME(longsleep): Only hang up locally is probably not ideal - maybe775      // an error message should be shown?776    });777  };778}779export function doIgnore(id) {780  return {781    type: types.KWM_DO_IGNORE,782    id,783  };784}785export function setLocalStream(stream) {786  return async () => {787    console.info('KWM setting local stream', stream); // eslint-disable-line no-console788    if (kwm && kwm.webrtc) {789      kwm.webrtc.setLocalStream(stream);790    }791    return stream;792  };793}794export function unsetLocalStream() {795  return async () => {796    console.info('KWM unsetting local stream'); // eslint-disable-line no-console797    if (kwm && kwm.webrtc) {798      kwm.webrtc.setLocalStream(); // clears.799    }800  };801}802export function setScreenshareStream(id, stream) {803  return async () => {804    console.info('KWM setting screen share stream', id, stream); // eslint-disable-line no-console805    if (kwm && kwm.webrtc) {806      kwm.webrtc.setScreenshareStream(id, stream);807    }808    return stream;809  };810}811export function setMode(mode) {812  return async () => {813    if (kwm && kwm.webrtc) {814      kwm.webrtc.setMode(mode);815    }816  };817}818export function updateOfferAnswerConstraints(options) {819  return async () => {820    console.info('KWM update offer/answer constaints', options); // eslint-disable-line no-console821    Object.assign(webrtcOptions.answerConstraints, options);822    Object.assign(webrtcOptions.offerConstraints, options);823    if (kwm && kwm.webrtc) {824      Object.assign(kwm.webrtc.options, webrtcOptions);825    }826  };827}828export function applyLocalStreamTracks(info) {829  return async dispatch => {830    if (!info || !info.stream) {831      return info;832    }833    console.info('KWM updating local stream tracks', info); // eslint-disable-line no-console834    if (kwm && kwm.webrtc) {835      if (info.newStream) {836        return dispatch(setLocalStream(info.newStream));837      }838      for (const track of info.removedTracks) {839        kwm.webrtc.removeLocalStreamTrack(track, info.stream);840      }841      for (const track of info.newTracks) {842        kwm.webrtc.addLocalStreamTrack(track, info.stream);843      }844    }845    return info;846  };847}848export function getStatsForAllConnections() {849  return async (dispatch, getState) => {850    const { connections } = getState().kwm;851    // Implement getStats according to https://www.w3.org/TR/webrtc-stats/#example-of-a-stats-application852    const promises = [];853    for (const id in connections) {854      const c = connections[id];855      if (c._pc) {856        try {857          const senders = c._pc.getSenders();858          const receivers = c._pc.getReceivers();859          senders.forEach(sender => {860            promises.push(sender.getStats());861          });862          receivers.forEach(receiver => {863            promises.push(receiver.getStats());864          });865        } catch (err) {866          console.warn('getStats failed', err); // eslint-disable-line no-console867        }868      }869    }870    if (promises.length === 0) {871      return null;872    }873    const result = {874      transportsBytesSend: 0,875      transportsBytesReceived: 0,876    };877    const reports = await Promise.all(promises);878    reports.forEach(report => {879      for (let record of report.values()) {880        //console.debug('getStats record', record.type, record.bytesSent, record.bytesReceived, record);881        switch (record.type) {882          case 'outbound-rtp':883            result.transportsBytesSend += record.bytesSent;884            break;885          case 'inbound-rtp':886            result.transportsBytesReceived += record.bytesReceived;887            break;888          case 'candidate-pair':889            break;890          default:891            continue;892        }893        if (!result.timestamp && record.timestamp) {894          // NOTE(longsleep): We use only a single timestamp, probably a little off ..895          result.timestamp = record.timestamp;896        }897      }898    });899    return result;900  };901}902export function tryGuestLogon(settings) {903  return dispatch => {904    return dispatch(guestLogon(settings)).catch(err => {905      console.debug('try guest logon failed', err); // eslint-disable-line no-console906      return {907        ok: false,908      };909    });910  };911}912function chatsMessageReceived(event, options={}) {913  const { channel, message, profile } = event;914  return {915    type: types.CHATS_MESSAGES_RECEIVED,916    channel,917    session: 'current',918    messages: [{919      ...message,920      ts: new Date(message.ts * 1000),921      profile,922    }],923    ...options,924  };925}926function chatsSystemReceived(event) {927  return async dispatch => {928    const { channel, message } = event;929    // Filter incoming messages to let only the ones through we know about.930    switch (message.kind) {931      case 'delivery_queued':932        return dispatch({933          type: types.CHATS_MESSAGES_DELIVERY_QUEUED,934          channel,935          session: 'current',936          ids: [message.id],937        });938      case 'system':939        // System message.940        return dispatch(chatsMessageReceived(event, { skipUnreadCounting: true }));941      default:942        console.warn('unknown chats system message kind received', message.kind); // eslint-disable-line no-console943    }944  };...

Full Screen

Full Screen

peercall.js

Source:peercall.js Github

copy

Full Screen

1/*2 * Spreed WebRTC.3 * Copyright (C) 2013-2014 struktur AG4 *5 * This file is part of Spreed WebRTC.6 *7 * This program is free software: you can redistribute it and/or modify8 * it under the terms of the GNU Affero General Public License as published by9 * the Free Software Foundation, either version 3 of the License, or10 * (at your option) any later version.11 *12 * This program is distributed in the hope that it will be useful,13 * but WITHOUT ANY WARRANTY; without even the implied warranty of14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the15 * GNU Affero General Public License for more details.16 *17 * You should have received a copy of the GNU Affero General Public License18 * along with this program.  If not, see <http://www.gnu.org/licenses/>.19 *20 */21"use strict";22define(['jquery', 'underscore', 'mediastream/utils', 'mediastream/peerconnection'], function($, _, utils, PeerConnection) {23	var PeerCall = function(webrtc, id, from, to) {24		this.webrtc = webrtc;25		this.id = id;26		this.from = from;27		this.to = to;28		this.e = $({}) // events29		this.mediaConstraints = $.extend(true, {}, this.webrtc.settings.mediaConstraints);30		this.pcConfig = $.extend(true, {}, this.webrtc.settings.pcConfig);31		this.pcConstraints = $.extend(true, {}, this.webrtc.settings.pcConstraints);32		this.sdpConstraints = $.extend(true, {}, this.webrtc.settings.sdpConstraints);33		this.offerConstraints = $.extend(true, {}, this.webrtc.settings.offerConstraints);34		this.sdpParams = $.extend(true, {}, this.webrtc.settings.sdpParams);35		this.peerconnection = null;36		this.datachannels = {};37		this.streams = {};38		this.negotiationNeeded = false;39		this.initiate = false;40		this.closed = false;41	};42	PeerCall.prototype.setInitiate = function(initiate) {43		this.initiate = !! initiate;44		//console.log("Set initiate", this.initiate, this);45	};46	PeerCall.prototype.createPeerConnection = function(success_cb, error_cb) {47		var peerconnection = this.peerconnection = new PeerConnection(this.webrtc, this);48		if (success_cb && peerconnection.pc) {49			success_cb(peerconnection);50		}51		if (error_cb && !peerconnection.pc) {52			// TODO(longsleep): Check if this can happen?53			error_cb(peerconnection);54		}55		return peerconnection;56	};57	PeerCall.prototype.createOffer = function(cb) {58		var constraints = utils.mergeConstraints(this.offerConstraints, this.sdpConstraints);59		console.log('Creating offer with constraints: \n' +60			'  \'' + JSON.stringify(constraints, null, '\t') + '\'.', this.negotiationNeeded);61		this.peerconnection.createOffer(_.bind(this.onCreateAnswerOffer, this, cb), _.bind(this.onErrorAnswerOffer, this), constraints);62	};63	PeerCall.prototype.createAnswer = function(cb) {64		console.log("Creating answer.", this.negotiationNeeded);65		this.peerconnection.createAnswer(_.bind(this.onCreateAnswerOffer, this, cb), _.bind(this.onErrorAnswerOffer, this), this.peerconnection.sdpConstraints);66	};67	PeerCall.prototype.onCreateAnswerOffer = function(cb, sessionDescription) {68		this.setLocalSdp(sessionDescription);69		// Convert to object to allow custom property injection.70		var sessionDescriptionObj = sessionDescription;71		if (sessionDescriptionObj.toJSON) {72			sessionDescriptionObj = JSON.parse(JSON.stringify(sessionDescriptionObj));73		}74		console.log("Created offer/answer", JSON.stringify(sessionDescriptionObj, null, "\t"));75		// Allow external session description modifications.76		this.e.triggerHandler("sessiondescription", [sessionDescriptionObj, this]);77		// Always set local description.78		this.peerconnection.setLocalDescription(sessionDescription, _.bind(function() {79			console.log("Set local session description.", sessionDescription, this);80			if (cb) {81				cb(sessionDescriptionObj, this);82			}83		}, this), _.bind(function(err) {84			console.error("Set local session description failed", err);85			this.close();86			this.e.triggerHandler("error", "failed_peerconnection_setup");87		}, this));88		if (this.negotiationNeeded)  {89			this.negotiationNeeded = false;90			console.log("Negotiation complete.", this);91		}92	};93	PeerCall.prototype.onErrorAnswerOffer = function(event) {94		console.error("Failed to create answer/offer", event);95	};96	PeerCall.prototype.setRemoteDescription = function(sessionDescription, cb) {97		var peerconnection = this.peerconnection;98		if (!peerconnection) {99			console.log("Got a remote description but not connected -> ignored.");100			return;101		}102		this.setRemoteSdp(sessionDescription);103		peerconnection.setRemoteDescription(sessionDescription, _.bind(function() {104			console.log("Set remote session description.", sessionDescription, this);105			if (cb) {106				cb(sessionDescription, this);107			}108			// NOTE(longsleep): There are several szenarios where onaddstream is never fired, when109			// the peer does not provide a certain stream type (eg. has no camera). See110			// for example https://bugzilla.mozilla.org/show_bug.cgi?id=998546. For this111			// reason we always trigger onRemoteStream added for all streams which are available112			// after the remote SDP was set successfully.113			_.defer(_.bind(function() {114				_.each(peerconnection.getRemoteStreams(), _.bind(function(stream) {115					if (!this.streams.hasOwnProperty(stream.id) && (stream.getAudioTracks().length > 0 || stream.getVideoTracks().length > 0)) {116						// NOTE(longsleep): Add stream here when it has at least one audio or video track, to avoid FF >= 33 to add it multiple times.117						console.log("Adding stream after remote SDP success.", stream);118						this.onRemoteStreamAdded(stream);119					}120				}, this));121			}, this));122		}, this), _.bind(function(err) {123			console.error("Set remote session description failed", err);124			this.close();125			this.e.triggerHandler("error", "failed_peerconnection_setup");126		}, this));127	};128	PeerCall.prototype.setLocalSdp = function(sessionDescription) {129		var params = this.sdpParams;130		sessionDescription.sdp = utils.maybePreferAudioReceiveCodec(sessionDescription.sdp, params);131		sessionDescription.sdp = utils.maybePreferVideoReceiveCodec(sessionDescription.sdp, params);132		sessionDescription.sdp = utils.maybeSetAudioReceiveBitRate(sessionDescription.sdp, params);133		sessionDescription.sdp = utils.maybeSetVideoReceiveBitRate(sessionDescription.sdp, params);134	};135	PeerCall.prototype.setRemoteSdp = function(sessionDescription) {136		var params = this.sdpParams;137		sessionDescription.sdp = utils.maybeSetOpusOptions(sessionDescription.sdp, params);138		sessionDescription.sdp = utils.maybePreferAudioSendCodec(sessionDescription.sdp, params);139		sessionDescription.sdp = utils.maybePreferVideoSendCodec(sessionDescription.sdp, params);140		sessionDescription.sdp = utils.maybeSetAudioSendBitRate(sessionDescription.sdp, params);141		sessionDescription.sdp = utils.maybeSetVideoSendBitRate(sessionDescription.sdp, params);142		sessionDescription.sdp = utils.maybeSetVideoSendInitialBitRate(sessionDescription.sdp, params);143	};144	PeerCall.prototype.onIceCandidate = function(event) {145		if (event.candidate) {146			//console.log("ice candidate", event.candidate);147			var payload = {148				type: 'candidate',149				sdpMLineIndex: event.candidate.sdpMLineIndex,150				sdpMid: event.candidate.sdpMid,151				candidate: event.candidate.candidate152			};153			// Allow external payload modifications.154			this.e.triggerHandler("icecandidate", [payload, this]);155			// Send it.156			// TODO(longsleep): This id needs to be different for PeerXfers.157			// XXX(longsleep): This seems to be breaking conferences when this.to and not this.id.158			this.webrtc.api.sendCandidate(this.to, payload);159			//console.log("Sent candidate", event.candidate.sdpMid, event.candidate.sdpMLineIndex, event.candidate.candidate);160		} else {161			console.log('End of candidates.');162		}163	};164	PeerCall.prototype.onIceConnectionStateChange = function(iceConnectionState) {165		this.e.triggerHandler("connectionStateChange", [iceConnectionState, this]);166	};167	PeerCall.prototype.onRemoteStreamAdded = function(stream) {168		var id = stream.id;169		if (this.streams.hasOwnProperty(id)) {170			return;171		}172		this.streams[id] = stream;173		this.e.triggerHandler("remoteStreamAdded", [stream, this]);174	};175	PeerCall.prototype.onRemoteStreamRemoved = function(stream) {176		this.e.triggerHandler("remoteStreamRemoved", [stream, this]);177		if (stream) {178			delete this.streams[stream.id];179		}180	};181	PeerCall.prototype.onNegotiationNeeded = function() {182		if (!this.negotiationNeeded) {183			this.negotiationNeeded = true;184			console.log("Negotiation needed.", this);185			this.e.triggerHandler("negotiationNeeded", [this]);186		}187	};188	PeerCall.prototype.addIceCandidate = function(candidate) {189		if (this.closed) {190			// Avoid errors when still receiving candidates but closed.191			return;192		}193		this.peerconnection.addIceCandidate(candidate, function() {194			//console.log("Remote candidate added successfully.", candidate);195		}, function(error) {196			console.warn("Failed to add remote candidate:", error, candidate);197		});198	};199	PeerCall.prototype.onDatachannel = function(datachannel) {200		//console.log("onDatachannel", datachannel);201		var label = datachannel.label;202		if (this.datachannels.hasOwnProperty(label)) {203			console.warn("Received duplicated datachannel label", label, datachannel, this.datachannels);204			return;205		}206		// Remember it for correct cleanups.207		this.datachannels[label] = datachannel;208		this.e.triggerHandler("datachannel", ["new", datachannel, this]);209	};210	PeerCall.prototype.onDatachannelDefault = function(state, datachannel) {211		if (state === "open") {212			//console.log("Data ready", this);213			_.defer(_.bind(function() {214				this.e.triggerHandler("dataReady", [this]);215			}, this));216		}217		this.e.triggerHandler("datachannel.default", [state, datachannel, this]);218	};219	PeerCall.prototype.onMessage = function(event) {220		//console.log("Peer to peer channel message", event);221		var data = event.data;222		if (data instanceof Blob) {223			console.warn("Blob data received - not implemented.", data);224		} else if (data instanceof ArrayBuffer) {225			console.warn("ArrayBuffer data received - not implemented.", data);226		} else if (typeof data === "string") {227			if (data.charCodeAt(0) === 2) {228				// Ignore whatever shit is this (sent by Chrome 34 and FireFox). Feel free to229				// change the comment it you know what this is.230				return;231			}232			//console.log("Datachannel message", [event.data, event.data.length, event.data.charCodeAt(0)]);233			var msg = JSON.parse(event.data);234			this.webrtc.api.received({235				Type: msg.Type,236				Data: msg,237				To: this.webrtc.api.id,238				From: this.id,239				p2p: true240			}); //XXX(longsleep): use event for this?241		} else {242			console.warn("Unknow data type received -> igored", typeof data, [data]);243		}244	};245	PeerCall.prototype.getDatachannel = function(label, init, create_cb) {246		//console.log("getDatachannel", label);247		var datachannel = this.datachannels[label];248		if (!datachannel) {249			console.log("Creating new datachannel", label, init);250			datachannel = this.peerconnection.createDatachannel(label, init);251			if (create_cb) {252				create_cb(datachannel);253			}254		}255		return datachannel;256	};257	PeerCall.prototype.close = function() {258		if (this.closed) {259			return;260		}261		this.closed = true;262		_.each(this.datachannels, function(datachannel) {263			datachannel.close();264		});265		this.datachannels = {};266		if (this.peerconnection) {267			this.peerconnection.close();268			this.peerconnection = null;269		}270		// Trigger event for all previously added streams.271		_.each(this.streams, _.bind(function(stream, id) {272			this.e.triggerHandler("remoteStreamRemoved", [stream, this]);273		}, this));274		this.streams = {};275		console.log("Peercall close", this);276		this.e.triggerHandler("closed", [this]);277	};278	return PeerCall;...

Full Screen

Full Screen

asyncbox-specs.js

Source:asyncbox-specs.js Github

copy

Full Screen

...15});16describe('longSleep', function () {17  it('should work like sleep in general', async function () {18    let now = Date.now();19    await longSleep(20);20    (Date.now() - now).should.be.above(19);21  });22  it('should work like sleep with values less than threshold', async function () {23    const now = Date.now();24    await longSleep(20, {thresholdMs: 100});25    (Date.now() - now).should.be.above(19);26  });27  it('should work like sleep with values above threshold, but quantized', async function () {28    const now = Date.now();29    await longSleep(50, {thresholdMs: 20, intervalMs: 40});30    (Date.now() - now).should.be.above(79);31  });32  it('should trigger a progress callback if specified', async function () {33    let callCount = 0;34    let curElapsed = 0;35    let curTimeLeft = 10000;36    let curProgress = 0;37    const progressCb = function ({elapsedMs, timeLeft, progress}) {38      elapsedMs.should.be.above(curElapsed);39      timeLeft.should.be.below(curTimeLeft);40      progress.should.be.above(curProgress);41      curElapsed = elapsedMs;42      curTimeLeft = timeLeft;43      curProgress = progress;44      callCount += 1;45    };46    const now = Date.now();47    await longSleep(500, {thresholdMs: 1, intervalMs: 100, progressCb});48    (Date.now() - now).should.be.above(49);49    callCount.should.be.above(3);50    (curProgress >= 1).should.be.true;51    (curTimeLeft <= 0).should.be.true;52    (curElapsed >= 50).should.be.true;53  });54});55describe('retry', function () {56  let okFnCalls = 0;57  let okFn = async function (val1, val2) {58    await sleep(15);59    okFnCalls++;60    return val1 * val2;61  };...

Full Screen

Full Screen

peerconnection.js

Source:peerconnection.js Github

copy

Full Screen

1"use strict";2define(['jquery', 'underscore', 'webrtc.adapter'], function($, _) {3	var count = 0;4	var dataChannelDefaultLabel = "default";5	var PeerConnection = function(webrtc, currentcall) {6		this.webrtc = webrtc;7		this.id = count++;8		this.currentcall = null;9		this.pc = null;10		this.datachannel = null;11		this.datachannelReady = false;12		this.readyForRenegotiation = true;13		if (currentcall) {14			this.createPeerConnection(currentcall);15		}16	};17	PeerConnection.prototype.setReadyForRenegotiation = function(ready) {18		this.readyForRenegotiation = !!ready;19	};20	PeerConnection.prototype.createPeerConnection = function(currentcall) {21		// XXX(longsleep): This function is a mess.22		var pc;23		if (currentcall) {24			this.currentcall = currentcall;25		} else {26			currentcall = this.currentcall;27		}28		try {29			// Create an RTCPeerConnection via the polyfill (adapter.js)30			console.log('Creating RTCPeerConnnection with:\n' +31				'  config: \'' + JSON.stringify(currentcall.pcConfig) + '\';\n' +32				'  constraints: \'' + JSON.stringify(currentcall.pcConstraints) + '\'.');33			pc = this.pc = new window.RTCPeerConnection(currentcall.pcConfig, currentcall.pcConstraints);34		} catch (e) {35			console.error('Failed to create PeerConnection, exception: ' + e.message);36			pc = this.pc = null;37		}38		if (pc) {39			// Bind peer connection events.40			pc.onicecandidate = _.bind(currentcall.onIceCandidate, currentcall);41			pc.oniceconnectionstatechange = _.bind(this.onIceConnectionStateChange, this)42			// NOTE(longsleep): There are several szenarios where onaddstream is never fired, when43			// the peer does not provide a certain stream type (eg. has no camera). See44			// for example https://bugzilla.mozilla.org/show_bug.cgi?id=998546.45			pc.onaddstream = _.bind(this.onRemoteStreamAdded, this);46			pc.onremovestream = _.bind(this.onRemoteStreamRemoved, this);47			// NOTE(longsleep): Firefox 38 has support for onaddtrack. Unfortunately Chrome does48			// not support this and thus both are not compatible. For the time being this means49			// that renegotiation does not work between Firefox and Chrome. Even worse, current50			// spec says that the event should really be named ontrack.51			if (window.webrtcDetectedBrowser === "firefox") {52				// NOTE(longsleep): onnegotiationneeded is not supported by Firefox < 38.53				// Also firefox does not care about streams, but has the newer API for tracks54				// implemented. This does not work together with Chrome, so we trigger negotiation55				// manually when a stream is added or removed.56				// https://bugzilla.mozilla.org/show_bug.cgi?id=101788857				// https://bugzilla.mozilla.org/show_bug.cgi?id=114983858				this.negotiationNeeded = _.bind(function() {59					if (this.currentcall.initiate) {60						// Trigger onNegotiationNeeded once for Firefox.61						console.log("Negotiation needed.");62						this.onNegotiationNeeded({target: this.pc});63					}64				}, this);65			} else {66				pc.onnegotiationneeded = _.bind(this.onNegotiationNeeded, this);67			}68			pc.ondatachannel = _.bind(this.onDatachannel, this);69			pc.onsignalingstatechange = _.bind(this.onSignalingStateChange, this);70			// NOTE(longsleep):71			// Support old callback too (https://groups.google.com/forum/?fromgroups=#!topic/discuss-webrtc/glukq0OWwVM)72			// Chrome < 27 and Firefox < 24 need this.73			pc.onicechange = _.bind(function(iceConnectionState) {74				//XXX(longsleep): Hack the compatibility to new style event.75				console.warn("Old style onicechange event", arguments);76				this.onIceConnectionStateChange({77					target: {78						iceConnectionState: iceConnectionState79					}80				});81			}, this);82			// Create default data channel when we are in initiate mode.83			if (currentcall.initiate) {84				if (window.webrtcDetectedBrowser !== "chrome" || !window.webrtcDetectedAndroid || (window.webrtcDetectedBrowser === "chrome" && window.webrtcDetectedVersion >= 33)) {85					// NOTE(longsleep): Android (Chrome 32) does have broken SCTP data channels86					// which makes connection fail because of sdp set error for answer/offer.87					// See https://code.google.com/p/webrtc/issues/detail?id=2253 Lets hope the88					// crap gets fixed with Chrome on Android 33. For now disable SCTP in flags89					// on Adroid to be able to accept offers with SCTP in it.90					// chrome://flags/#disable-sctp-data-channels91					this.createDatachannel(dataChannelDefaultLabel, {92						ordered: true93					});94				}95			}96		}97		return pc;98	};99	PeerConnection.prototype.negotiationNeeded = function() {100		// Per default this does nothing as the browser is expected to handle this.101	};102	PeerConnection.prototype.createDatachannel = function(label, init) {103		if (!label) {104			console.error("Refusing to create a datachannel without a label.", label, init);105			return;106		}107		var rtcinit = $.extend({}, init);108		console.debug("Creating datachannel:", label, rtcinit, this);109		// Create datachannel.110		var datachannel;111		try {112			datachannel = this.pc.createDataChannel(label, rtcinit);113			// Fake onDatachannel event.114			this.onDatachannel({115				channel: datachannel116			});117		} catch (e) {118			console.error('Failed to create DataChannel, exception: ' + e.message);119			if (label === dataChannelDefaultLabel) {120				this.datachannel = null;121				this.datachannelReady = false;122			}123		}124		return datachannel;125	};126	PeerConnection.prototype.onDatachannel = function(event) {127		var datachannel = event.channel;128		if (datachannel) {129			if (datachannel.label === dataChannelDefaultLabel) {130				datachannel.binaryType = "arraybuffer";131				// We handle the default data channel ourselves.132				console.debug("Got default datachannel", datachannel.label, this.id, datachannel, this);133				this.datachannel = datachannel;134				var eventHandler = _.bind(this.currentcall.onDatachannelDefault, this.currentcall);135				// Bind datachannel events and settings.136				datachannel.onmessage = _.bind(this.currentcall.onMessage, this.currentcall);137				datachannel.onopen = _.bind(function(event) {138					console.log("Datachannel opened", datachannel.label, this.id, event);139					this.datachannelReady = true;140					eventHandler("open", datachannel);141				}, this);142				datachannel.onclose = _.bind(function(event) {143					console.log("Datachannel closed", datachannel.label, this.id, event);144					this.datachannelReady = false;145					eventHandler("close", datachannel);146				}, this);147				datachannel.onerror = _.bind(function(event) {148					console.warn("Datachannel error", datachannel.label, this.id, event);149					this.datachannelReady = false;150					eventHandler("error", datachannel);151				}, this);152			} else {153				// Delegate.154				console.debug("Got datachannel", datachannel.label, this.id, datachannel);155				_.defer(_.bind(this.currentcall.onDatachannel, this.currentcall), datachannel);156			}157		}158	};159	PeerConnection.prototype.send = function(data) {160		if (!this.datachannelReady) {161			console.error("Unable to send message by datachannel because datachannel is not ready.", data);162			return;163		}164		if (data instanceof Blob) {165			this.datachannel.send(data);166		} else if (data instanceof ArrayBuffer) {167			this.datachannel.send(data);168		} else {169			try {170				this.datachannel.send(JSON.stringify(data));171			} catch (e) {172				console.warn("Data channel failed to send string -> closing.", e);173				this.datachannelReady = false;174				this.datachannel.close();175			}176		}177	};178	PeerConnection.prototype.onSignalingStateChange = function(event) {179		var signalingState = event.target.signalingState;180		console.debug("Connection signaling state change", signalingState, this.currentcall.id);181		this.currentcall.onSignalingStateChange(signalingState);182	};183	PeerConnection.prototype.onIceConnectionStateChange = function(event) {184		var iceConnectionState = event.target.iceConnectionState;185		console.debug("ICE connection state change", iceConnectionState, this.currentcall.id);186		this.currentcall.onIceConnectionStateChange(iceConnectionState);187	};188	PeerConnection.prototype.onRemoteStreamAdded = function(event) {189		var stream = event.stream;190		console.info('Remote stream added.', stream);191		this.currentcall.onRemoteStreamAdded(stream);192	};193	PeerConnection.prototype.onRemoteStreamRemoved = function(event) {194		var stream = event.stream;195		console.info('Remote stream removed.', stream);196		this.currentcall.onRemoteStreamRemoved(stream);197	};198	PeerConnection.prototype.onNegotiationNeeded = function(event) {199		var peerconnection = event.target;200		if (peerconnection === this.pc) {201			this.currentcall.onNegotiationNeeded();202		}203	};204	PeerConnection.prototype.close = function() {205		if (this.datachannel) {206			this.datachannel.close()207		}208		if (this.pc) {209			this.pc.close();210		}211		this.datachannel = null;212		this.pc = null;213	};214	PeerConnection.prototype.hasRemoteDescription = function() {215		// NOTE(longsleep): Chrome seems to return empty sdp even if no remoteDescription was set.216		if (!this.pc || !this.pc.remoteDescription || !this.pc.remoteDescription.sdp) {217			return false218		}219		return true;220	};221	PeerConnection.prototype.setRemoteDescription = function() {222		return this.pc.setRemoteDescription.apply(this.pc, arguments);223	};224	PeerConnection.prototype.setLocalDescription = function() {225		return this.pc.setLocalDescription.apply(this.pc, arguments);226	};227	PeerConnection.prototype.addIceCandidate = function() {228		return this.pc.addIceCandidate.apply(this.pc, arguments);229	};230	PeerConnection.prototype.addStream = function() {231		_.defer(this.negotiationNeeded);232		return this.pc.addStream.apply(this.pc, arguments);233	};234	PeerConnection.prototype.removeStream = function() {235		_.defer(this.negotiationNeeded);236		return this.pc.removeStream.apply(this.pc, arguments);237	};238	PeerConnection.prototype.createAnswer = function() {239		return this.pc.createAnswer.apply(this.pc, arguments);240	};241	PeerConnection.prototype.createOffer = function() {242		return this.pc.createOffer.apply(this.pc, arguments);243	};244	PeerConnection.prototype.getRemoteStreams = function() {245		if (!this.pc) {246			return [];247		}248		return this.pc.getRemoteStreams.apply(this.pc, arguments);249	};250	PeerConnection.prototype.getLocalStreams = function() {251		if (!this.pc) {252			return [];253		}254		return this.pc.getRemoteStreams.apply(this.pc, arguments);255	};256	PeerConnection.prototype.getStreamById = function() {257		return this.pc.getStreamById.apply(this.pc, arguments);258	};259	return PeerConnection;...

Full Screen

Full Screen

CopperMiner.js

Source:CopperMiner.js Github

copy

Full Screen

1var robot = require('robotjs');2var shortsleep = getRandomInt(100, 700);3var mediumSleep = getRandomInt(1200, 2000);4var longSleep = getRandomInt(2100, 5000);5var extraSleep = getRandomInt(5100, 9832);6// console.log(robot.getPixelColor(1164, 521))7// console.log(robot.getPixelColor(1309, 515))8// console.log(robot.getPixelColor(1145, 437))9// console.log(robot.getPixelColor(1216, 385))10// console.log(robot.getPixelColor(1097, 362))11// console.log(robot.getPixelColor(1031, 411))12// console.log(robot.getPixelColor(1154, 504))13var endInventory_x = 1889, endInventory_y = 930, beginningInventory_x = 1743, beginningInventory_y = 715;14var copperOreInventoryColor = "cc6a2a", tinOreInventoryColor = "746b6b";15var endInventoryPixelColor = robot.getPixelColor(endInventory_x, endInventory_y);16var copperOre_x, copperOre_y, endingTinOre_x, endingTinOre_y;17var caveExit_x = 1122, caveExit_y = 444, compassLocation_x = 1695, compassLocation_y = 78;18var besideBank_x = 1341, besideBank_y = 118, bank_x = 859, bank_y = 302;19var bankOreBox_x = 777, bankOreBox_y = 490, faceSouth_x = compassLocation_x, faceSouth_y = compassLocation_y + 45;20var caveFront_x = 1087, caveFront_y = 110, caveEntrance_x = 1731, caveEntrance_y = 525;21copperOre_x = 958;22copperOre_y = 508;23endingTinOre_x = 917;24endingTinOre_y = 594;25Miner();26function Miner() {27    console.log("Initialzing client...");28    sleep(mediumSleep);29    while (true) {30        var endInventory_x = 1889, endInventory_y = 930;31        var tinOreInventoryColor = "746b6b";32        var endInventoryPixelColor = robot.getPixelColor(endInventory_x, endInventory_y);33        var startingTinOre_x = 803, startingTinOre_y = 883, startingCopperOre_x = 903, startingCopperOre_y = 474;34        console.log("Beginning to mine copper ore.")35        mineCopper();36        console.log("Filled up on copper ore. Now mining tin ore.")37        robot.moveMouseSmooth(startingTinOre_x, startingTinOre_y);38        sleep(shortsleep);39        robot.mouseClick();40        mineTin();41        console.log("Filling up inventory for the final time.");42        robot.moveMouseSmooth(endingTinOre_x, endingTinOre_y);43        sleep(shortsleep);44        robot.mouseClick();45        while (endInventoryPixelColor != tinOreInventoryColor) {46            sleep(longSleep);47            robot.mouseClick();48            endInventoryPixelColor = robot.getPixelColor(endInventory_x, endInventory_y);49        }50        goToBank();51        console.log("Going back to the original spot.");52        robot.moveMouseSmooth(startingCopperOre_x, startingCopperOre_y);53        sleep(shortsleep);54        robot.mouseClick();55        56        console.log("Ending loop...");57    }58}59function mineCopper() {60    for (i = 0; i < 4; i++) {61        console.log("Copper ore inventory number: " + i);62        sleep(shortsleep);63        robot.moveMouseSmooth(copperOre_x, copperOre_y);64        sleep(shortsleep);65        robot.mouseClick();66        endInventoryPixelColor = robot.getPixelColor(endInventory_x, endInventory_y);67            while (endInventoryPixelColor != copperOreInventoryColor) {68                sleep(longSleep);69                robot.mouseClick();70                console.log("Waiting to fill inventory with copper ore...");71                endInventoryPixelColor = robot.getPixelColor(endInventory_x, endInventory_y);72            }73        console.log("Filling up ore box with copper ore.");74        sleep(shortsleep);75        robot.moveMouseSmooth(beginningInventory_x, beginningInventory_y);76        sleep(shortsleep);77        robot.mouseClick();78    }79}80function mineTin() {81    for (i = 0; i < 4; i++) {82        console.log("Tin ore inventory number: " + i);83        sleep(mediumSleep);84        robot.moveMouseSmooth(endingTinOre_x, endingTinOre_y);85        sleep(shortsleep)86        robot.mouseClick();87        endInventoryPixelColor = robot.getPixelColor(endInventory_x, endInventory_y);88            while (endInventoryPixelColor != tinOreInventoryColor) {89                sleep(longSleep);90                robot.mouseClick();91                console.log("Waiting to fill inventory up with tin ore...");92                endInventoryPixelColor = robot.getPixelColor(endInventory_x, endInventory_y);93            }94        95        console.log("Filling up ore box with tin ore.");96        sleep(shortsleep);97        robot.moveMouseSmooth(beginningInventory_x, beginningInventory_y);98        sleep(shortsleep);99        robot.mouseClick();100    }101}102function goToBank() {103    console.log("Leaving cave.");104    sleep(shortsleep);105    robot.moveMouseSmooth(caveExit_x, caveExit_y);106    sleep(shortsleep);107    robot.mouseClick();108    sleep(longSleep);109    console.log("Facing north.");110    robot.moveMouseSmooth(compassLocation_x, compassLocation_y);111    sleep(shortsleep);112    robot.mouseClick();113    sleep(shortsleep);114    console.log("Going to bank.");115    robot.moveMouseSmooth(besideBank_x, besideBank_y);116    sleep(shortsleep);117    robot.mouseClick();118    sleep(extraSleep);119    console.log("Banking.");120    robot.moveMouseSmooth(bank_x, bank_y);121    sleep(shortsleep);122    robot.mouseClick();123    sleep(mediumSleep);124    console.log("Depositing inventory.");125    robot.keyTap("3");126    sleep(shortsleep);127    console.log("Getting ore box back.");128    robot.moveMouseSmooth(bankOreBox_x, bankOreBox_y);129    sleep(shortsleep);130    robot.mouseClick();131    sleep(shortsleep);132    console.log("Leaving bank.");133    robot.keyTap("escape");134    sleep(shortsleep);135    console.log("Facing south.");136    robot.moveMouseSmooth(compassLocation_x, compassLocation_y);137    sleep(shortsleep);138    robot.mouseClick("right");139    sleep(shortsleep);140    robot.moveMouseSmooth(faceSouth_x, faceSouth_y);141    sleep(shortsleep);142    robot.mouseClick();143    sleep(shortsleep);144    console.log("Going beside cave.");145    robot.moveMouseSmooth(caveFront_x, caveFront_y);146    sleep(shortsleep);147    robot.mouseClick();148    sleep(extraSleep);149    console.log("Entering cave.");150    robot.moveMouseSmooth(caveEntrance_x, caveEntrance_y);151    sleep(shortsleep);152    robot.mouseClick();153    sleep(mediumSleep);154    console.log("Facing north.");155    robot.moveMouseSmooth(compassLocation_x, compassLocation_y);156    sleep(shortsleep);157    robot.mouseClick()158    sleep(shortsleep);159}160function sleep(ms) {161    Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);162}163function getRandomInt(min, max) {164    min = Math.ceil(min);165    max = Math.floor(max);166    return Math.floor(Math.random() * (max - min + 1)) + min;...

Full Screen

Full Screen

loadPricingContext.js

Source:loadPricingContext.js Github

copy

Full Screen

...51    });52    i += delta;53    helper.shortSleep();54  }55  helper.longSleep();56  helper.writeToTopic(task.workflowInstanceId);57  await koor.postStatus(task, {58    status: "InProgress",59    message: `${global_percentage +60      allocated_percentage}% Load ${what} PTF DONE`61  });62}63koor.pollingLoop(namespace, name, async task => {64  await load(task, "position", 0, 25);65  await load(task, "products", 25, 25);66  await load(task, "static data", 50, 25);67  await load(task, "market data", 75, 25);68  helper.longSleep();69  await koor.postStatus(task, {70    status: "Completed",71    outputValues: {72      id_ref_data: uuid()73    }74  });...

Full Screen

Full Screen

metamask-sign-auto.js

Source:metamask-sign-auto.js Github

copy

Full Screen

1/*2 * @Title: Metamask Sign Auto3 * @Description: Automatically signs trivial metamask signature requests4 */5(function () {6    let clicks = 0;7    const sleep = 150;8    const longSleep = 3000;9    let clickSign = () => {10        let div = document.getElementsByClassName('request-signature__rows')[0];11        if (!div) return;12        if (!div.innerText.includes('I would like to follow user')) return;13        Array.from(document.getElementsByClassName('button')).filter((el) => el.getAttribute('data-testid') && el.getAttribute('data-testid') == 'request-signature__sign').forEach((el) => el.click());14        console.log('clicks:' + (++clicks));15        if (clicks % 50 == 0) {16            console.log('sleeping...');17            setTimeout(clickSign, longSleep);18        } else {19            setTimeout(clickSign, sleep);20        }21    };22    setTimeout(clickSign, 5000);...

Full Screen

Full Screen

helper.js

Source:helper.js Github

copy

Full Screen

...6}7function shortSleep() {8  randomSleep(1);9}10function longSleep() {11  randomSleep(5);12}13function writeToTopic(topic) {14  if (!fs.existsSync(dir)) {15    console.log("topics folder doesn't exist, creating it");16    fs.mkdirSync(dir);17  }18  console.log("writeToTopic", topic);19  fs.closeSync(fs.openSync(dir + topic, "w"));20}21function readFromTopic(topic) {22  while (!fs.existsSync(dir + topic)) {23    console.log("readFromTopic", topic);24    longSleep();25  }26}27module.exports = {28  shortSleep,29  longSleep,30  writeToTopic,31  readFromTopic...

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Appium Android Driver automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful