<commit_before>// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';

function detectTextIntent(projectId, sessionId, queries, languageCode) {
  // [START dialogflow_detect_intent_text]

  /**
   * TODO(developer): UPDATE these variables before running the sample.
   */
  // projectId: ID of the GCP project where Dialogflow agent is deployed
  // const projectId = 'PROJECT_ID';
  // sessionId: Random number or hashed user identifier
  // const sessionId = 123456;
  // queries: A set of sequential queries to be send to Dialogflow agent for Intent Detection
  // const queries = [
  //   'Reserve a meeting room in Toronto office, there will be 5 of us',
  //   'Next monday at 3pm for 1 hour, please', // Tell the bot when the meeting is taking place
  //   'B'  // Rooms are defined on the Dialogflow agent, default options are A, B, or C
  // ]
  // languageCode: Indicates the language Dialogflow agent should use to detect intents
  // const languageCode = 'en';

  // Imports the Dialogflow library
  const dialogflow = require('dialogflow');

  // Instantiates a session client
  const sessionClient = new dialogflow.SessionsClient();

  async function detectIntent(
    projectId,
    sessionId,
    query,
    contexts,
    languageCode
  ) {
    // The path to identify the agent that owns the created intent.
    const sessionPath = sessionClient.sessionPath(projectId, sessionId);

    // The text query request.
    const request = {
      session: sessionPath,
      queryInput: {
        text: {
          text: query,
          languageCode: languageCode,
        },
      },
    };

    if (contexts && contexts.length > 0) {
      request.queryParams = {
        contexts: contexts,
      };
    }

    const responses = await sessionClient.detectIntent(request);
    return responses[0];
  }

  async function executeQueries(projectId, sessionId, queries, languageCode) {
    // Keeping the context across queries let's us simulate an ongoing conversation with the bot
    let context;
    let intentResponse;
    for (const query of queries) {
      try {
        console.log(`Sending Query: ${query}`);
        intentResponse = await detectIntent(
          projectId,
          sessionId,
          query,
          context,
          languageCode
        );
        console.log('Detected intent');
        console.log(
          `Fulfillment Text: ${intentResponse.queryResult.fulfillmentText}`
        );
        // Use the context from this response for next queries
        context = intentResponse.queryResult.outputContexts;
      } catch (error) {
        console.log(error);
      }
    }
  }
  executeQueries(projectId, sessionId, queries, languageCode);
  // [END dialogflow_detect_intent_text]
}

async function detectEventIntent(
  projectId,
  sessionId,
  eventName,
  languageCode
) {
  const {struct} = require('pb-util');

  // Imports the Dialogflow library
  const dialogflow = require('dialogflow');

  // Instantiates a session client
  const sessionClient = new dialogflow.SessionsClient();

  // The path to identify the agent that owns the created intent.
  const sessionPath = sessionClient.sessionPath(projectId, sessionId);

  // The text query request.
  const request = {
    session: sessionPath,
    queryInput: {
      event: {
        name: eventName,
        parameters: struct.encode({foo: 'bar'}),
        languageCode: languageCode,
      },
    },
  };

  const [response] = await sessionClient.detectIntent(request);
  console.log('Detected intent');
  const result = response.queryResult;
  // Instantiates a context client
  const contextClient = new dialogflow.ContextsClient();

  console.log(`  Query: ${result.queryText}`);
  console.log(`  Response: ${result.fulfillmentText}`);
  if (result.intent) {
    console.log(`  Intent: ${result.intent.displayName}`);
  } else {
    console.log(`  No intent matched.`);
  }
  const parameters = JSON.stringify(struct.decode(result.parameters));
  console.log(`  Parameters: ${parameters}`);
  if (result.outputContexts && result.outputContexts.length) {
    console.log(`  Output contexts:`);
    result.outputContexts.forEach(context => {
      const contextId = contextClient.matchContextFromContextName(context.name);
      const contextParameters = JSON.stringify(
        struct.decode(context.parameters)
      );
      console.log(`    ${contextId}`);
      console.log(`      lifespan: ${context.lifespanCount}`);
      console.log(`      parameters: ${contextParameters}`);
    });
  }
}

async function detectAudioIntent(
  projectId,
  sessionId,
  filename,
  encoding,
  sampleRateHertz,
  languageCode
) {
  // [START dialogflow_detect_intent_audio]
  const fs = require('fs');
  const util = require('util');
  const {struct} = require('pb-util');
  // Imports the Dialogflow library
  const dialogflow = require('dialogflow');

  // Instantiates a session client
  const sessionClient = new dialogflow.SessionsClient();

  // The path to identify the agent that owns the created intent.
  const sessionPath = sessionClient.sessionPath(projectId, sessionId);

  // Read the content of the audio file and send it as part of the request.
  const readFile = util.promisify(fs.readFile);
  const inputAudio = await readFile(filename);
  const request = {
    session: sessionPath,
    queryInput: {
      audioConfig: {
        audioEncoding: encoding,
        sampleRateHertz: sampleRateHertz,
        languageCode: languageCode,
      },
    },
    inputAudio: inputAudio,
  };

  // Recognizes the speech in the audio and detects its intent.
  const [response] = await sessionClient.detectIntent(request);

  console.log('Detected intent:');
  const result = response.queryResult;
  // Instantiates a context client
  const contextClient = new dialogflow.ContextsClient();

  console.log(`  Query: ${result.queryText}`);
  console.log(`  Response: ${result.fulfillmentText}`);
  if (result.intent) {
    console.log(`  Intent: ${result.intent.displayName}`);
  } else {
    console.log(`  No intent matched.`);
  }
  const parameters = JSON.stringify(struct.decode(result.parameters));
  console.log(`  Parameters: ${parameters}`);
  if (result.outputContexts && result.outputContexts.length) {
    console.log(`  Output contexts:`);
    result.outputContexts.forEach(context => {
      const contextId = contextClient.matchContextFromContextName(context.name);
      const contextParameters = JSON.stringify(
        struct.decode(context.parameters)
      );
      console.log(`    ${contextId}`);
      console.log(`      lifespan: ${context.lifespanCount}`);
      console.log(`      parameters: ${contextParameters}`);
    });
  }
  // [END dialogflow_detect_intent_audio]
}

async function streamingDetectIntent(
  projectId,
  sessionId,
  filename,
  encoding,
  sampleRateHertz,
  languageCode
) {
  // [START dialogflow_detect_intent_streaming]
  const fs = require('fs');
  const util = require('util');
  const {Transform, pipeline} = require('stream');
  const {struct} = require('pb-util');

  const pump = util.promisify(pipeline);
  // Imports the Dialogflow library
  const dialogflow = require('dialogflow');

  // Instantiates a session client
  const sessionClient = new dialogflow.SessionsClient();

  // The path to the local file on which to perform speech recognition, e.g.
  // /path/to/audio.raw const filename = '/path/to/audio.raw';

  // The encoding of the audio file, e.g. 'AUDIO_ENCODING_LINEAR_16'
  // const encoding = 'AUDIO_ENCODING_LINEAR_16';

  // The sample rate of the audio file in hertz, e.g. 16000
  // const sampleRateHertz = 16000;

  // The BCP-47 language code to use, e.g. 'en-US'
  // const languageCode = 'en-US';
  const sessionPath = sessionClient.sessionPath(projectId, sessionId);

  const initialStreamRequest = {
    session: sessionPath,
    queryInput: {
      audioConfig: {
        audioEncoding: encoding,
        sampleRateHertz: sampleRateHertz,
        languageCode: languageCode,
      },
      singleUtterance: true,
    },
  };

  // Create a stream for the streaming request.
  const detectStream = sessionClient
    .streamingDetectIntent()
    .on('error', console.error)
    .on('data', data => {
      if (data.recognitionResult) {
        console.log(
          `Intermediate transcript: ${data.recognitionResult.transcript}`
        );
      } else {
        console.log(`Detected intent:`);

        const result = data.queryResult;
        // Instantiates a context client
        const contextClient = new dialogflow.ContextsClient();

        console.log(`  Query: ${result.queryText}`);
        console.log(`  Response: ${result.fulfillmentText}`);
        if (result.intent) {
          console.log(`  Intent: ${result.intent.displayName}`);
        } else {
          console.log(`  No intent matched.`);
        }
        const parameters = JSON.stringify(struct.decode(result.parameters));
        console.log(`  Parameters: ${parameters}`);
        if (result.outputContexts && result.outputContexts.length) {
          console.log(`  Output contexts:`);
          result.outputContexts.forEach(context => {
            const contextId = contextClient.matchContextFromContextName(
              context.name
            );
            const contextParameters = JSON.stringify(
              struct.decode(context.parameters)
            );
            console.log(`    ${contextId}`);
            console.log(`      lifespan: ${context.lifespanCount}`);
            console.log(`      parameters: ${contextParameters}`);
          });
        }
      }
    });

  // Write the initial stream request to config for audio input.
  detectStream.write(initialStreamRequest);

  // Stream an audio file from disk to the Conversation API, e.g.
  // "./resources/audio.raw"
  await pump(
    fs.createReadStream(filename),
    // Format the audio stream into the request format.
    new Transform({
      objectMode: true,
      transform: (obj, _, next) => {
        next(null, {inputAudio: obj});
      },
    }),
    detectStream
  );
  // [END dialogflow_detect_intent_streaming]
}

const cli = require(`yargs`)
  .demand(1)
  .options({
    projectId: {
      alias: 'p',
      default: process.env.GCLOUD_PROJECT || process.env.GOOGLE_CLOUD_PROJECT,
      description:
        'The Project ID to use. Defaults to the value of the ' +
        'GCLOUD_PROJECT or GOOGLE_CLOUD_PROJECT environment variables.',
      requiresArg: true,
      type: 'string',
    },
    sessionId: {
      alias: 's',
      default: require('uuid/v1')(),
      type: 'string',
      requiresArg: true,
      description:
        'The identifier of the detect session. Defaults to a random UUID.',
    },
    languageCode: {
      alias: 'l',
      default: 'en-US',
      type: 'string',
      requiresArg: true,
      description: 'The language code of the query. Defaults to "en-US".',
    },
    encoding: {
      alias: 'e',
      default: 'AUDIO_ENCODING_LINEAR_16',
      choices: [
        'AUDIO_ENCODING_LINEAR_16',
        'AUDIO_ENCODING_FLAC',
        'AUDIO_ENCODING_MULAW',
        'AUDIO_ENCODING_AMR',
        'AUDIO_ENCODING_AMR_WB',
        'AUDIO_ENCODING_OGG_OPUS',
        'AUDIO_ENCODING_SPEEX_WITH_HEADER_BYTE',
      ],
      requiresArg: true,
      description: 'The encoding of the input audio.',
    },
    sampleRateHertz: {
      alias: 'r',
      type: 'number',
      description:
        'The sample rate in Hz of the input audio. Only ' +
        'required if the input audio is in raw format.',
    },
  })
  .demandOption(
    'projectId',
    "Please provide your Dialogflow agent's project ID with the -p flag or through the GOOGLE_CLOUD_PROJECT env var"
  )
  .command(
    `text`,
    `Detects the intent for text queries.`,
    {
      queries: {
        alias: 'q',
        array: true,
        string: true,
        demandOption: true,
        requiresArg: true,
        description: 'An array of text queries',
      },
    },
    opts =>
      detectTextIntent(
        opts.projectId,
        opts.sessionId,
        opts.queries,
        opts.languageCode
      )
  )
  .command(
    `event <eventName>`,
    `Detects the intent for a client-generated event name.`,
    {},
    opts =>
      detectEventIntent(
        opts.projectId,
        opts.sessionId,
        opts.eventName,
        opts.languageCode
      )
  )
  .command(
    `audio <filename>`,
    `Detects the intent for audio queries in a local file.`,
    {},
    opts =>
      detectAudioIntent(
        opts.projectId,
        opts.sessionId,
        opts.filename,
        opts.encoding,
        opts.sampleRateHertz,
        opts.languageCode
      )
  )
  .command(
    `stream <filename>`,
    `Detects the intent in a local audio file by streaming it to the ` +
      `Conversation API.`,
    {},
    opts =>
      streamingDetectIntent(
        opts.projectId,
        opts.sessionId,
        opts.filename,
        opts.encoding,
        opts.sampleRateHertz,
        opts.languageCode
      )
  )
  .example(
    `node $0 text -q "hello" "book a room" "Mountain View" ` +
      `"today" "230pm" "half an hour" "two people" "A" "yes"`
  )
  .example(`node $0 event order_pizza`)
  .example(`node $0 audio resources/book_a_room.wav -r 16000`)
  .example(`node $0 stream resources/mountain_view.wav -r 16000`)
  .wrap(120)
  .recommendCommands()
  .epilogue(
    `For more information, see https://cloud.google.com/dialogflow-enterprise/docs`
  )
  .help()
  .strict();

if (module === require.main) {
  cli.parse(process.argv.slice(2));
}
<commit_msg>docs: correct typo in comment (#568)<commit_after>// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';

function detectTextIntent(projectId, sessionId, queries, languageCode) {
  // [START dialogflow_detect_intent_text]

  /**
   * TODO(developer): UPDATE these variables before running the sample.
   */
  // projectId: ID of the GCP project where Dialogflow agent is deployed
  // const projectId = 'PROJECT_ID';
  // sessionId: String representing a random number or hashed user identifier
  // const sessionId = '123456';
  // queries: A set of sequential queries to be send to Dialogflow agent for Intent Detection
  // const queries = [
  //   'Reserve a meeting room in Toronto office, there will be 5 of us',
  //   'Next monday at 3pm for 1 hour, please', // Tell the bot when the meeting is taking place
  //   'B'  // Rooms are defined on the Dialogflow agent, default options are A, B, or C
  // ]
  // languageCode: Indicates the language Dialogflow agent should use to detect intents
  // const languageCode = 'en';

  // Imports the Dialogflow library
  const dialogflow = require('dialogflow');

  // Instantiates a session client
  const sessionClient = new dialogflow.SessionsClient();

  async function detectIntent(
    projectId,
    sessionId,
    query,
    contexts,
    languageCode
  ) {
    // The path to identify the agent that owns the created intent.
    const sessionPath = sessionClient.sessionPath(projectId, sessionId);

    // The text query request.
    const request = {
      session: sessionPath,
      queryInput: {
        text: {
          text: query,
          languageCode: languageCode,
        },
      },
    };

    if (contexts && contexts.length > 0) {
      request.queryParams = {
        contexts: contexts,
      };
    }

    const responses = await sessionClient.detectIntent(request);
    return responses[0];
  }

  async function executeQueries(projectId, sessionId, queries, languageCode) {
    // Keeping the context across queries let's us simulate an ongoing conversation with the bot
    let context;
    let intentResponse;
    for (const query of queries) {
      try {
        console.log(`Sending Query: ${query}`);
        intentResponse = await detectIntent(
          projectId,
          sessionId,
          query,
          context,
          languageCode
        );
        console.log('Detected intent');
        console.log(
          `Fulfillment Text: ${intentResponse.queryResult.fulfillmentText}`
        );
        // Use the context from this response for next queries
        context = intentResponse.queryResult.outputContexts;
      } catch (error) {
        console.log(error);
      }
    }
  }
  executeQueries(projectId, sessionId, queries, languageCode);
  // [END dialogflow_detect_intent_text]
}

async function detectEventIntent(
  projectId,
  sessionId,
  eventName,
  languageCode
) {
  const {struct} = require('pb-util');

  // Imports the Dialogflow library
  const dialogflow = require('dialogflow');

  // Instantiates a session client
  const sessionClient = new dialogflow.SessionsClient();

  // The path to identify the agent that owns the created intent.
  const sessionPath = sessionClient.sessionPath(projectId, sessionId);

  // The text query request.
  const request = {
    session: sessionPath,
    queryInput: {
      event: {
        name: eventName,
        parameters: struct.encode({foo: 'bar'}),
        languageCode: languageCode,
      },
    },
  };

  const [response] = await sessionClient.detectIntent(request);
  console.log('Detected intent');
  const result = response.queryResult;
  // Instantiates a context client
  const contextClient = new dialogflow.ContextsClient();

  console.log(`  Query: ${result.queryText}`);
  console.log(`  Response: ${result.fulfillmentText}`);
  if (result.intent) {
    console.log(`  Intent: ${result.intent.displayName}`);
  } else {
    console.log(`  No intent matched.`);
  }
  const parameters = JSON.stringify(struct.decode(result.parameters));
  console.log(`  Parameters: ${parameters}`);
  if (result.outputContexts && result.outputContexts.length) {
    console.log(`  Output contexts:`);
    result.outputContexts.forEach(context => {
      const contextId = contextClient.matchContextFromContextName(context.name);
      const contextParameters = JSON.stringify(
        struct.decode(context.parameters)
      );
      console.log(`    ${contextId}`);
      console.log(`      lifespan: ${context.lifespanCount}`);
      console.log(`      parameters: ${contextParameters}`);
    });
  }
}

async function detectAudioIntent(
  projectId,
  sessionId,
  filename,
  encoding,
  sampleRateHertz,
  languageCode
) {
  // [START dialogflow_detect_intent_audio]
  const fs = require('fs');
  const util = require('util');
  const {struct} = require('pb-util');
  // Imports the Dialogflow library
  const dialogflow = require('dialogflow');

  // Instantiates a session client
  const sessionClient = new dialogflow.SessionsClient();

  // The path to identify the agent that owns the created intent.
  const sessionPath = sessionClient.sessionPath(projectId, sessionId);

  // Read the content of the audio file and send it as part of the request.
  const readFile = util.promisify(fs.readFile);
  const inputAudio = await readFile(filename);
  const request = {
    session: sessionPath,
    queryInput: {
      audioConfig: {
        audioEncoding: encoding,
        sampleRateHertz: sampleRateHertz,
        languageCode: languageCode,
      },
    },
    inputAudio: inputAudio,
  };

  // Recognizes the speech in the audio and detects its intent.
  const [response] = await sessionClient.detectIntent(request);

  console.log('Detected intent:');
  const result = response.queryResult;
  // Instantiates a context client
  const contextClient = new dialogflow.ContextsClient();

  console.log(`  Query: ${result.queryText}`);
  console.log(`  Response: ${result.fulfillmentText}`);
  if (result.intent) {
    console.log(`  Intent: ${result.intent.displayName}`);
  } else {
    console.log(`  No intent matched.`);
  }
  const parameters = JSON.stringify(struct.decode(result.parameters));
  console.log(`  Parameters: ${parameters}`);
  if (result.outputContexts && result.outputContexts.length) {
    console.log(`  Output contexts:`);
    result.outputContexts.forEach(context => {
      const contextId = contextClient.matchContextFromContextName(context.name);
      const contextParameters = JSON.stringify(
        struct.decode(context.parameters)
      );
      console.log(`    ${contextId}`);
      console.log(`      lifespan: ${context.lifespanCount}`);
      console.log(`      parameters: ${contextParameters}`);
    });
  }
  // [END dialogflow_detect_intent_audio]
}

async function streamingDetectIntent(
  projectId,
  sessionId,
  filename,
  encoding,
  sampleRateHertz,
  languageCode
) {
  // [START dialogflow_detect_intent_streaming]
  const fs = require('fs');
  const util = require('util');
  const {Transform, pipeline} = require('stream');
  const {struct} = require('pb-util');

  const pump = util.promisify(pipeline);
  // Imports the Dialogflow library
  const dialogflow = require('dialogflow');

  // Instantiates a session client
  const sessionClient = new dialogflow.SessionsClient();

  // The path to the local file on which to perform speech recognition, e.g.
  // /path/to/audio.raw const filename = '/path/to/audio.raw';

  // The encoding of the audio file, e.g. 'AUDIO_ENCODING_LINEAR_16'
  // const encoding = 'AUDIO_ENCODING_LINEAR_16';

  // The sample rate of the audio file in hertz, e.g. 16000
  // const sampleRateHertz = 16000;

  // The BCP-47 language code to use, e.g. 'en-US'
  // const languageCode = 'en-US';
  const sessionPath = sessionClient.sessionPath(projectId, sessionId);

  const initialStreamRequest = {
    session: sessionPath,
    queryInput: {
      audioConfig: {
        audioEncoding: encoding,
        sampleRateHertz: sampleRateHertz,
        languageCode: languageCode,
      },
      singleUtterance: true,
    },
  };

  // Create a stream for the streaming request.
  const detectStream = sessionClient
    .streamingDetectIntent()
    .on('error', console.error)
    .on('data', data => {
      if (data.recognitionResult) {
        console.log(
          `Intermediate transcript: ${data.recognitionResult.transcript}`
        );
      } else {
        console.log(`Detected intent:`);

        const result = data.queryResult;
        // Instantiates a context client
        const contextClient = new dialogflow.ContextsClient();

        console.log(`  Query: ${result.queryText}`);
        console.log(`  Response: ${result.fulfillmentText}`);
        if (result.intent) {
          console.log(`  Intent: ${result.intent.displayName}`);
        } else {
          console.log(`  No intent matched.`);
        }
        const parameters = JSON.stringify(struct.decode(result.parameters));
        console.log(`  Parameters: ${parameters}`);
        if (result.outputContexts && result.outputContexts.length) {
          console.log(`  Output contexts:`);
          result.outputContexts.forEach(context => {
            const contextId = contextClient.matchContextFromContextName(
              context.name
            );
            const contextParameters = JSON.stringify(
              struct.decode(context.parameters)
            );
            console.log(`    ${contextId}`);
            console.log(`      lifespan: ${context.lifespanCount}`);
            console.log(`      parameters: ${contextParameters}`);
          });
        }
      }
    });

  // Write the initial stream request to config for audio input.
  detectStream.write(initialStreamRequest);

  // Stream an audio file from disk to the Conversation API, e.g.
  // "./resources/audio.raw"
  await pump(
    fs.createReadStream(filename),
    // Format the audio stream into the request format.
    new Transform({
      objectMode: true,
      transform: (obj, _, next) => {
        next(null, {inputAudio: obj});
      },
    }),
    detectStream
  );
  // [END dialogflow_detect_intent_streaming]
}

const cli = require(`yargs`)
  .demand(1)
  .options({
    projectId: {
      alias: 'p',
      default: process.env.GCLOUD_PROJECT || process.env.GOOGLE_CLOUD_PROJECT,
      description:
        'The Project ID to use. Defaults to the value of the ' +
        'GCLOUD_PROJECT or GOOGLE_CLOUD_PROJECT environment variables.',
      requiresArg: true,
      type: 'string',
    },
    sessionId: {
      alias: 's',
      default: require('uuid/v1')(),
      type: 'string',
      requiresArg: true,
      description:
        'The identifier of the detect session. Defaults to a random UUID.',
    },
    languageCode: {
      alias: 'l',
      default: 'en-US',
      type: 'string',
      requiresArg: true,
      description: 'The language code of the query. Defaults to "en-US".',
    },
    encoding: {
      alias: 'e',
      default: 'AUDIO_ENCODING_LINEAR_16',
      choices: [
        'AUDIO_ENCODING_LINEAR_16',
        'AUDIO_ENCODING_FLAC',
        'AUDIO_ENCODING_MULAW',
        'AUDIO_ENCODING_AMR',
        'AUDIO_ENCODING_AMR_WB',
        'AUDIO_ENCODING_OGG_OPUS',
        'AUDIO_ENCODING_SPEEX_WITH_HEADER_BYTE',
      ],
      requiresArg: true,
      description: 'The encoding of the input audio.',
    },
    sampleRateHertz: {
      alias: 'r',
      type: 'number',
      description:
        'The sample rate in Hz of the input audio. Only ' +
        'required if the input audio is in raw format.',
    },
  })
  .demandOption(
    'projectId',
    "Please provide your Dialogflow agent's project ID with the -p flag or through the GOOGLE_CLOUD_PROJECT env var"
  )
  .command(
    `text`,
    `Detects the intent for text queries.`,
    {
      queries: {
        alias: 'q',
        array: true,
        string: true,
        demandOption: true,
        requiresArg: true,
        description: 'An array of text queries',
      },
    },
    opts =>
      detectTextIntent(
        opts.projectId,
        opts.sessionId,
        opts.queries,
        opts.languageCode
      )
  )
  .command(
    `event <eventName>`,
    `Detects the intent for a client-generated event name.`,
    {},
    opts =>
      detectEventIntent(
        opts.projectId,
        opts.sessionId,
        opts.eventName,
        opts.languageCode
      )
  )
  .command(
    `audio <filename>`,
    `Detects the intent for audio queries in a local file.`,
    {},
    opts =>
      detectAudioIntent(
        opts.projectId,
        opts.sessionId,
        opts.filename,
        opts.encoding,
        opts.sampleRateHertz,
        opts.languageCode
      )
  )
  .command(
    `stream <filename>`,
    `Detects the intent in a local audio file by streaming it to the ` +
      `Conversation API.`,
    {},
    opts =>
      streamingDetectIntent(
        opts.projectId,
        opts.sessionId,
        opts.filename,
        opts.encoding,
        opts.sampleRateHertz,
        opts.languageCode
      )
  )
  .example(
    `node $0 text -q "hello" "book a room" "Mountain View" ` +
      `"today" "230pm" "half an hour" "two people" "A" "yes"`
  )
  .example(`node $0 event order_pizza`)
  .example(`node $0 audio resources/book_a_room.wav -r 16000`)
  .example(`node $0 stream resources/mountain_view.wav -r 16000`)
  .wrap(120)
  .recommendCommands()
  .epilogue(
    `For more information, see https://cloud.google.com/dialogflow-enterprise/docs`
  )
  .help()
  .strict();

if (module === require.main) {
  cli.parse(process.argv.slice(2));
}
<|endoftext|>


<commit_before>define([

  'Backbone',

  //Templates
  'text!templates/project-page/closeGameTemplate.html'
], function(

  Backbone,

  //Template
  closeGameTemplate
){
  var GameController = Backbone.View.extend({

    template: _.template(closeGameTemplate),

    close: function(event){
      var task = this.selectedTask.get('id');
      socket.emit('close game', task);
    },

    killTask: function(){
      var task = this.selectedTask.get('id');
      var kill = _.once(function(){
        socket.emit('kill task', task);
      });

      kill();
    },

    render: function(){
      var estimations = this.selectedTask.get('estimated') || [];
      var time        = this.selectedTask.get('time');
      var total       = _.countBy(estimations, function(estimation){
        return estimation.card;
      });

      var max    = _.max(total, function(point){return point;});

      var result = _.compact(_.map(total, function(count, point){
        return count === max ? point : false;
      })).pop();

      if(!estimations[0]){
        estimations.push({
          player: 'No one estimated',
          card: '?'
        });
      }

      if(time === '0'){
        this.killTask();
      }

      this.selectedTask.set({result: result}, {silent: true});

      this.$el.html(this.template({
        estimations: estimations,
        time: time,
        result: result
      }));

    }

  });

  return GameController;
});
<commit_msg>Remove destroy card from game controller<commit_after>define([

  'Backbone',

  //Templates
  'text!templates/project-page/closeGameTemplate.html'
], function(

  Backbone,

  //Template
  closeGameTemplate
){
  var GameController = Backbone.View.extend({

    template: _.template(closeGameTemplate),

    close: function(event){
      var task = this.selectedTask.get('id');
      socket.emit('close game', task);
    },

    render: function(){
      var estimations = this.selectedTask.get('estimated') || [];
      var time        = this.selectedTask.get('time');
      var total       = _.countBy(estimations, function(estimation){
        return estimation.card;
      });

      var max    = _.max(total, function(point){return point;});

      var result = _.compact(_.map(total, function(count, point){
        return count === max ? point : false;
      })).pop();

      this.selectedTask.set({result: result}, {silent: true});

      if(time === '0'){
        time = 'Ended';
      }

      this.$el.html(this.template({
        estimations: estimations,
        time: time,
        result: result
      }));

    }

  });

  return GameController;
});
<|endoftext|>


<commit_before>"use strict";

//
// Mainloop
//

var mainLoop = function(options) {
  console.log("\n#" + mainLoop.iteration);

  // Force update all
  if (options && options.forceUpdate === true) {
    popup.update.all();
  }
  // Regular update intervals
  else {
    if (ls.showCantina === 'true')
      if (mainLoop.iteration % UPDATE_CANTINAS_INTERVAL === 0)
        popup.update.cantinas();
    if (ls.showBus === 'true')
      if (mainLoop.iteration % UPDATE_BUS_INTERVAL === 0)
        popup.update.bus();
    if (mainLoop.iteration % UPDATE_NEWS_INTERVAL === 0)
      popup.update.affiliationNews(1);
    if (ls.showAffiliation2 === 'true')
      if (mainLoop.iteration % UPDATE_NEWS_INTERVAL === 0)
        popup.update.affiliationNews(2);
    // Only if hardware
    if (Affiliation.org[ls.affiliationKey1].hw) {
      if (mainLoop.iteration % UPDATE_AFFILIATION_INTERVAL === 0) {
        Browser.getBackgroundProcess().updateAffiliation(function() {
          popup.update.meeting();
          popup.update.servant();
          popup.update.coffee();
          // popup.update.status(); // TODO: No status info in popup yet
        });
      }
    }
  }

  // No reason to count to infinity
  if (10000 < mainLoop.iteration)
    mainLoop.iteration = 0;
  else
    mainLoop.iteration++;
}
mainLoop.iteration = 0;
mainLoop.intervalId = null;

//
// Tiny Screen Check
// (executes itself once)
//

(function tinyScreenCheck() {
  // Netbook or MacBook Air? 800x600 won't do.
  // If this is a tiny computer screen, reduce popup height
  if (window.screen.availHeight < 700) {
    var shorter = window.screen.availHeight - 100;
    // shorter is available screenspace minus the height
    // of the browser taskbar, rounded up well to be sure
    $('body').css('height', shorter + 'px');
  }
}());

//
// Show And Hide Elements
// (executes itself once)
//

(function showAndHideElements() {
  // Show stuff that the user hasn't explicitly removed yet
  if (ls.closedSpecialNews !== $('#specialNews a').attr('href')) $('#specialNews').show();
  // Hide stuff the user can't or doesn't want to see
  if (typeof Affiliation.org[ls.affiliationKey1].hw === "undefined") $('div#todays').hide();
  if (ls.showCantina !== 'true') $('div#cantinas').hide();
  if (ls.showBus !== 'true') $('div#bus').hide();

  // If only one affiliation is to be shown remove the second news column
  // Also, some serious statistics
  if (ls.showAffiliation2 !== 'true') {
    // Show correct news column(s)
    $('#news #full').show();
    // Who uses single affiliations?
    Analytics.trackEvent('loadSingleAffiliation', ls.affiliationKey1);
    // What is the prefered primary affiliation?
    Analytics.trackEvent('loadAffiliation1', ls.affiliationKey1);
  }
  else {
    // Show correct news column(s)
    $('#news #left').show();
    $('#news #right').show();
    // What kind of double affiliations are used?
    Analytics.trackEvent('loadDoubleAffiliation', ls.affiliationKey1 + ' - ' + ls.affiliationKey2);
    // What is the prefered primary affiliation?
    Analytics.trackEvent('loadAffiliation1', ls.affiliationKey1);
    // What is the prefered secondary affiliation?
    Analytics.trackEvent('loadAffiliation2', ls.affiliationKey2);
  }
}());

//
// Apply Affiliation Settings
// (executes itself once AND is usable later)
//

var applyAffiliationSettings = (function() {

  var apply = function() {
    // Applying affiliation graphics
    var key = ls.affiliationKey1;
    var logo = Affiliation.org[key].logo;
    var icon = Affiliation.org[key].icon;
    var placeholder = Affiliation.org[key].placeholder;
    $('#logo').prop('src', logo);
    $('link[rel="shortcut icon"]').prop('href', icon);

    // News placeholder graphics
    if (ls.showAffiliation2 === 'true') {
      $('div#news div#left article img').prop('src', placeholder);
    }
    else {
      $('div#news div#full article img').prop('src', placeholder);
    }

    // Chatter button, if applicable
    if (Affiliation.org[ls.affiliationKey1].slack) {
        $('#chatterButton').show();
    }
    else {
      $('#chatterButton').hide();
    }

    // Apply the affiliation's own name for it's office
    if (Affiliation.org[ls.affiliationKey1].hw) {

      var statusIcons = Affiliation.org[ls.affiliationKey1].hw.statusIcons;
      // Apply affiliation icons in options
      $('span[data="ICON_OPEN"]').html('');
      $('span[data="ICON_CLOSED"]').html('');
      $('span[data="ICON_MEETING"]').html('');

      // Apply affiliation names
      var officeName = Affiliation.org[ls.affiliationKey1].hw.office;
      $('#todays #schedule .title').text(officeName);
      $('span[data="officeName"]').text(officeName);
    }
  }

  apply(); // Run once
  return apply; // Save for later use

}());

//
// Add version and changelog to div#tips
// (executes itself once)
//

(function addToTips() {
  // Add app version
  var appVersion = chrome.app.getDetails().version.match(/^\d+\.\d+/)[0];
  $('span[data="appVersion"]').text(appVersion);

  // Add CHANGELOG.md to div#tips
  Ajaxer.getPlainText({
    url: "CHANGELOG.md",
    success: function(data) {
      var converter = new Markdown.Converter();
      var html = converter.makeHtml(data);
      $("div#changelog").html(html);
      // Rebind tips links
      popup.event.bindTipsLinks();
    },
    error: function(e) {
      console.error('Could not include CHANGELOG.md because:', e);
    },
  });
}());

//
// DEBUG
// (executes itself once)
//

(function() {
  if (DEBUG) {
    // Show the DEBUG affiliation
    $('optgroup.debugAffiliation').show();
  }
}());

//
// Document ready function
//

$(document).ready(function() {

  // Enter main loop, keeping everything up-to-date
  var stayUpdated = function(now) {
    console.info(ONLINE_MESSAGE);
    var loopTimeout = (DEBUG ? PAGE_LOOP_DEBUG : PAGE_LOOP);
    // Schedule for repetition ...
    mainLoop.intervalId = setInterval( function() {
      mainLoop();
    }, loopTimeout);
    // ... and run once right now (just wait 2 secs to avoid network-change errors)
    var timeout = (now ? 0 : 2000);
    setTimeout( function() {
      mainLoop({forceUpdate: true});
    }, timeout);
  }
  // When offline mainloop is stopped to decrease power consumption
  window.addEventListener('online', stayUpdated);
  window.addEventListener('offline', function() {
    console.warn(OFFLINE_MESSAGE);
    clearInterval(mainLoop.intervalId);
    popup.update.bus();
  });
  // Go
  if (navigator.onLine)
    stayUpdated({forceUpdate: true});
  else
    mainLoop();

  // Hook up all event handlers
  popup.event.bindAll();
  // Load all localStorage values into inline options
  popup.options.loadAll();
  // Hoop up all option handlers
  popup.options.bindAll();

  // Set the cursor to focus on the question field
  // (e.g. Chrome on Windows doesn't do this automatically so I blatantly blame Windows)
  $('#oracle #question').focus();
  // Repeat for good measure (the browser may sometimes blur the question-field)
  setTimeout(function() {$('#oracle #question').focus();}, 400);

  // Track popularity of the chosen palette, the palette
  // itself is loaded a lot earlier for perceived speed
  Analytics.trackEvent('loadPalette', ls.affiliationPalette);

});
<commit_msg>popup: very minor bugfix<commit_after>"use strict";

//
// Mainloop
//

var mainLoop = function(options) {
  console.log("\n#" + mainLoop.iteration);

  // Force update all
  if (options && options.forceUpdate === true) {
    popup.update.all();
  }
  // Regular update intervals
  else {
    if (ls.showCantina === 'true')
      if (mainLoop.iteration % UPDATE_CANTINAS_INTERVAL === 0)
        popup.update.cantinas();
    if (ls.showBus === 'true')
      if (mainLoop.iteration % UPDATE_BUS_INTERVAL === 0)
        popup.update.bus();
    if (mainLoop.iteration % UPDATE_NEWS_INTERVAL === 0)
      popup.update.affiliationNews(1);
    if (ls.showAffiliation2 === 'true')
      if (mainLoop.iteration % UPDATE_NEWS_INTERVAL === 0)
        popup.update.affiliationNews(2);
    // Only if hardware
    if (Affiliation.org[ls.affiliationKey1].hw) {
      if (mainLoop.iteration % UPDATE_AFFILIATION_INTERVAL === 0) {
        Browser.getBackgroundProcess().updateAffiliation(function() {
          popup.update.meeting();
          popup.update.servant();
          popup.update.coffee();
          // popup.update.status(); // TODO: No status info in popup yet
        });
      }
    }
  }

  // No reason to count to infinity
  if (10000 < mainLoop.iteration)
    mainLoop.iteration = 0;
  else
    mainLoop.iteration++;
}
mainLoop.iteration = 0;
mainLoop.intervalId = null;

//
// Tiny Screen Check
// (executes itself once)
//

(function tinyScreenCheck() {
  // Netbook or MacBook Air? 800x600 won't do.
  // If this is a tiny computer screen, reduce popup height
  if (window.screen.availHeight < 700) {
    var shorter = window.screen.availHeight - 100;
    // shorter is available screenspace minus the height
    // of the browser taskbar, rounded up well to be sure
    $('body').css('height', shorter + 'px');
  }
}());

//
// Show And Hide Elements
// (executes itself once)
//

(function showAndHideElements() {
  // Show stuff that the user hasn't explicitly removed yet
  if (ls.closedSpecialNews !== $('#specialNews a').attr('href')) $('#specialNews').show();
  // Hide stuff the user can't or doesn't want to see
  if (typeof Affiliation.org[ls.affiliationKey1].hw === "undefined") $('div#todays').hide();
  if (ls.showCantina !== 'true') $('div#cantinas').hide();
  if (ls.showBus !== 'true') $('div#bus').hide();

  // If only one affiliation is to be shown remove the second news column
  // Also, some serious statistics
  if (ls.showAffiliation2 !== 'true') {
    // Show correct news column(s)
    $('#news #full').show();
    // Who uses single affiliations?
    Analytics.trackEvent('loadSingleAffiliation', ls.affiliationKey1);
    // What is the prefered primary affiliation?
    Analytics.trackEvent('loadAffiliation1', ls.affiliationKey1);
  }
  else {
    // Show correct news column(s)
    $('#news #left').show();
    $('#news #right').show();
    // What kind of double affiliations are used?
    Analytics.trackEvent('loadDoubleAffiliation', ls.affiliationKey1 + ' - ' + ls.affiliationKey2);
    // What is the prefered primary affiliation?
    Analytics.trackEvent('loadAffiliation1', ls.affiliationKey1);
    // What is the prefered secondary affiliation?
    Analytics.trackEvent('loadAffiliation2', ls.affiliationKey2);
  }
}());

//
// Apply Affiliation Settings
// (executes itself once AND is usable later)
//

var applyAffiliationSettings = (function() {

  var apply = function() {
    // Applying affiliation graphics
    var key = ls.affiliationKey1;
    var name = Affiliation.org[key].name;
    var logo = Affiliation.org[key].logo;
    var icon = Affiliation.org[key].icon;
    var placeholder = Affiliation.org[key].placeholder;

    // Graphics
    $('#logo').prop('src', logo);
    $('link[rel="shortcut icon"]').prop('href', icon); // Favicon has no purpose, yet, but hell, we're prepared

    // Chatter button, if applicable
    if (Affiliation.org[ls.affiliationKey1].slack) {
        $('#chatterButton').show();
    }
    else {
      $('#chatterButton').hide();
    }

    // Apply the affiliation's own name for it's office
    if (Affiliation.org[ls.affiliationKey1].hw) {

      var statusIcons = Affiliation.org[ls.affiliationKey1].hw.statusIcons;
      // Apply affiliation icons in options
      $('span[data="ICON_OPEN"]').html('');
      $('span[data="ICON_CLOSED"]').html('');
      $('span[data="ICON_MEETING"]').html('');

      // Apply affiliation names
      var officeName = Affiliation.org[ls.affiliationKey1].hw.office;
      $('#todays #schedule .title').text(officeName);
      $('span[data="officeName"]').text(officeName);
    }

    // News title (also set when news updates, this is a backup for an edge case)
    $('div#news div#left .title').text(name);

    // News placeholder graphics
    if (ls.showAffiliation2 === 'true') {
      $('div#news div#left article img').prop('src', placeholder);
    }
    else {
      $('div#news div#full article img').prop('src', placeholder);
    }
  }

  apply(); // Run once
  return apply; // Save for later use

}());

//
// Add version and changelog to div#tips
// (executes itself once)
//

(function addToTips() {
  // Add app version
  var appVersion = chrome.app.getDetails().version.match(/^\d+\.\d+/)[0];
  $('span[data="appVersion"]').text(appVersion);

  // Add CHANGELOG.md to div#tips
  Ajaxer.getPlainText({
    url: "CHANGELOG.md",
    success: function(data) {
      var converter = new Markdown.Converter();
      var html = converter.makeHtml(data);
      $("div#changelog").html(html);
      // Rebind tips links
      popup.event.bindTipsLinks();
    },
    error: function(e) {
      console.error('Could not include CHANGELOG.md because:', e);
    },
  });
}());

//
// DEBUG
// (executes itself once)
//

(function() {
  if (DEBUG) {
    // Show the DEBUG affiliation
    $('optgroup.debugAffiliation').show();
  }
}());

//
// Document ready function
//

$(document).ready(function() {

  // Enter main loop, keeping everything up-to-date
  var stayUpdated = function(now) {
    console.info(ONLINE_MESSAGE);
    var loopTimeout = (DEBUG ? PAGE_LOOP_DEBUG : PAGE_LOOP);
    // Schedule for repetition ...
    mainLoop.intervalId = setInterval( function() {
      mainLoop();
    }, loopTimeout);
    // ... and run once right now (just wait 2 secs to avoid network-change errors)
    var timeout = (now ? 0 : 2000);
    setTimeout( function() {
      mainLoop({forceUpdate: true});
    }, timeout);
  }
  // When offline mainloop is stopped to decrease power consumption
  window.addEventListener('online', stayUpdated);
  window.addEventListener('offline', function() {
    console.warn(OFFLINE_MESSAGE);
    clearInterval(mainLoop.intervalId);
    popup.update.bus();
  });
  // Go
  if (navigator.onLine)
    stayUpdated({forceUpdate: true});
  else
    mainLoop();

  // Hook up all event handlers
  popup.event.bindAll();
  // Load all localStorage values into inline options
  popup.options.loadAll();
  // Hoop up all option handlers
  popup.options.bindAll();

  // Set the cursor to focus on the question field
  // (e.g. Chrome on Windows doesn't do this automatically so I blatantly blame Windows)
  $('#oracle #question').focus();
  // Repeat for good measure (the browser may sometimes blur the question-field)
  setTimeout(function() {$('#oracle #question').focus();}, 400);

  // Track popularity of the chosen palette, the palette
  // itself is loaded a lot earlier for perceived speed
  Analytics.trackEvent('loadPalette', ls.affiliationPalette);

});
<|endoftext|>


<commit_before>'use strict';

var slugify = require('slugify');
var erro = require('utils/erro-ajax');

module.exports = {
  controller: function (args) {
    this.filtro = m.prop('');
    this.servicos = m.prop([]);

    this.servicosFiltrados = function () {
      var servicos;

      if (_.isEmpty(_.trim(this.filtro()))) {
        servicos = this.servicos();
      } else {
        var f = new RegExp(_.trim(_.deburr(this.filtro())), 'i');
        servicos = this.servicos().filter(function (i) {
          return f.test(i.id);
        });
      }

      return _.take(servicos, 25);
    };

    this.listarServicos = _.debounce(function () {
      m.request({
          method: 'GET',
          url: '/editar/api/servicos'
        })
        .then(this.servicos, erro);
    }.bind(this), 500);

    this.excluirServico = function (id) {
      m.request({
        method: 'DELETE',
        url: '/editar/api/servico/' + slugify(id),
      }).then(this.listarServicos, erro);
    };

    this.listarServicos();
  },

  view: function (ctrl) {
    return m('#conteudo', [
      m('span.cabecalho-cor'),
      m('#wrapper', [
        m.component(require('componentes/cabecalho')),

        m('#bem-vindo', [
          m('h2', 'Bem-vindo!'),

          m('input[type=search][placeholder="Filtrar por..."]', {
            oninput: m.withAttr('value', ctrl.filtro)
          }),

          m('table', [
            m('tr', [
              m('th[width="40%"]', 'Nome'),
              m('th.center', 'Autor'),
              m('th.center', 'Última atualização'),
              m('th.right', '')
            ])
          ].concat(ctrl.servicosFiltrados().map(function (s) {
            return m('tr', [

              m('td', m('a', {
                href: '/editar/servico/' + slugify(s.id)
              }, [
                s.id.replace(/\.xml$/, '').replace(/-/g, ' ')
              ])),

              m('td.center', s.autor),

              m('td.center', moment(s.horario).fromNow()),

              m('td.right', [
                m('a', {
                  href: '/editar/servico/' + slugify(s.id)
                }, m('button', [
                  m('span.fa.fa-pencil')
                ])),
                  m('button', {
                  onclick: _.bind(ctrl.excluirServico, ctrl, s.id)
                }, [
                  m('span.fa.fa-trash-o')
                ])
              ])
            ]);
          })))
        ])
      ])
    ]);
  }
};
<commit_msg>Exibe tempo relativo no locale correto<commit_after>'use strict';

var slugify = require('slugify');
var erro = require('utils/erro-ajax');

module.exports = {
  controller: function (args) {
    this.filtro = m.prop('');
    this.servicos = m.prop([]);

    this.servicosFiltrados = function () {
      var servicos;

      if (_.isEmpty(_.trim(this.filtro()))) {
        servicos = this.servicos();
      } else {
        var f = new RegExp(_.trim(_.deburr(this.filtro())), 'i');
        servicos = this.servicos().filter(function (i) {
          return f.test(i.id);
        });
      }

      return _.take(servicos, 25);
    };

    this.listarServicos = _.debounce(function () {
      m.request({
          method: 'GET',
          url: '/editar/api/servicos'
        })
        .then(this.servicos, erro);
    }.bind(this), 500);

    this.excluirServico = function (id) {
      m.request({
        method: 'DELETE',
        url: '/editar/api/servico/' + slugify(id),
      }).then(this.listarServicos, erro);
    };

    this.listarServicos();
  },

  view: function (ctrl) {
    moment.locale('pt-br');

    return m('#conteudo', [
      m('span.cabecalho-cor'),
      m('#wrapper', [
        m.component(require('componentes/cabecalho')),

        m('#bem-vindo', [
          m('h2', 'Bem-vindo!'),

          m('input[type=search][placeholder="Filtrar por..."]', {
            oninput: m.withAttr('value', ctrl.filtro)
          }),

          m('table', [
            m('tr', [
              m('th[width="40%"]', 'Nome'),
              m('th.center', 'Autor'),
              m('th.center', 'Última atualização'),
              m('th.right', '')
            ])
          ].concat(ctrl.servicosFiltrados().map(function (s) {
            return m('tr', [

              m('td', m('a', {
                href: '/editar/servico/' + slugify(s.id)
              }, [
                s.id.replace(/\.xml$/, '').replace(/-/g, ' ')
              ])),

              m('td.center', s.autor),

              m('td.center', moment(s.horario).fromNow()),

              m('td.right', [
                m('a', {
                  href: '/editar/servico/' + slugify(s.id)
                }, m('button', [
                  m('span.fa.fa-pencil')
                ])),
                  m('button', {
                  onclick: _.bind(ctrl.excluirServico, ctrl, s.id)
                }, [
                  m('span.fa.fa-trash-o')
                ])
              ])
            ]);
          })))
        ])
      ])
    ]);
  }
};
<|endoftext|>


<commit_before>import { CliTrackerController } from 'azk/cli/cli_tracker_controller';
import { Helpers } from 'azk/cli/helpers';
import { _, config, lazy_require } from 'azk';
import { defer, asyncUnsubscribe } from 'azk/utils/promises';
import { subscribe } from 'azk/utils/postal';

var lazy = lazy_require({
  Manifest: ['azk/manifest'],
  docker  : ['azk/docker', 'default'],
});

class Shell extends CliTrackerController {
  index() {
    var { options } = this.normalized_params;
    var args = this.normalized_params.arguments;

    var _subscription = subscribe('docker.pull.status', (data) => {
      Helpers.newPullProgressBar(this.ui)(data);
    });

    return asyncUnsubscribe(this, _subscription, function* () {
      var dir = this.cwd;
      var manifest, system;

      yield Helpers.requireAgent(this.ui);

      if (options.image) {
        // Arbitrary image
        manifest = lazy.Manifest.makeFake(dir, options.image);
        system   = manifest.systemDefault;
      } else {
        manifest = new lazy.Manifest(dir, true);
        Helpers.manifestValidate(this.ui, manifest);

        system   = manifest.systemDefault;
        if (args.system) {
          system = manifest.system(args.system, true);
        }
      }

      if (_.isString(options.command)) {
        options.command = `${options.command};`;
      }
      var commands = _.compact([ options.command, ...args['shell-args']]);
      var tty_default = options.tty || _.isEmpty(commands);
      var tty = (options['no-tty']) ? (options.tty || false) : tty_default;

      var stdin = this.ui.stdin();
      stdin.custom_pipe = () => { };

      var cmd_options  = {
        interactive: tty,
        pull   : this.ui.stdout(),
        stdout : this.ui.stdout(),
        stderr : this.ui.stderr(),
        stdin  : stdin,
        workdir: options.cwd || null,
      };

      // Support extra envs, ports and mount volumes
      cmd_options.envs   = this._parse_option(options.env  , /.+=.+/, '=', 'invalid_env');
      cmd_options.mounts = this._parse_option(options.mount, /.+:.+:?.*/, ':', 'invalid_mount', 1, (opts) => {
        return { type: (opts[2] ? opts[1] : 'path'), value: (opts[2] ? opts[2] : opts[0]) };
      });

      // TODO add support to `-- [shell-args]`
      var cmd = [options.shell || system.shell];
      if (!_.isEmpty(commands)) {
        cmd.push("-c");
        cmd.push(commands.join(' '));
      }
      cmd = _.compact(cmd);

      // Remove container before run
      var is_remove = !options['no-remove'] ? config("docker:remove_container") : !options['no-remove'];
      cmd_options = _.merge(cmd_options, {
        build_force    : options.rebuild || false,
        provision_force: (options.rebuild ? true : options.reprovision) || false,
        remove         : is_remove,
      });

      var result = defer((resolver, reject) => {
        var escape = (key, container, next) => {
          if (key === ".") {
            process.nextTick(() => {
              lazy.docker.getContainer(container).stop({ t: 5000 }).catch(reject);
            });
            return true;
          } else if (key === "?") {
            this.ok("coming soon...");
            process.nextTick(() => next());
            return true;
          }
          return false;
        };

        var _subscription_run = subscribe('docker.run.status', (data) => {
          this._escapeAndPullProgress(escape, system,
            !options.silent, options.verbose, options.stdout)(data);
        });

        system
          .runShell(cmd, cmd_options)
          .then(function (result) {
            _subscription_run.unsubscribe();
            return result;
          })
          .then(resolver, reject)
          .catch(function (err) {
            _subscription_run.unsubscribe();
            throw err;
          });
      });

      result = yield result.catch((error) => {
        return this.parseError(error);
      });

      return result.code;
    });
  }

  parseError(error) {
    if (error.statusCode) {
      if (error.statusCode === 404 && error.reason === "no such container") {
        this.ui.fail("commands.shell.ended.removed");
        return { code: 127 };
      }
    } else if (error.code === 'ECONNRESET') {
      this.ui.fail("commands.shell.ended.docker_end");
      return { code: 127 };
    } else if (error.code === 'ECONNREFUSED') {
      this.ui.fail("commands.shell.ended.docker_not_found");
      return { code: 127 };
    }
    throw error;
  }

  _escapeAndPullProgress(escape, system, show_logs, verbose) {
    return (event) => {
      var pullProgressBar = Helpers.newPullProgressBar(this.ui);
      var escapeCapture   = Helpers.escapeCapture(escape);

      // show verbose output
      if (verbose && event.stream) {
        this.ui.stdout().write('  ' + event.stream);
      }

      if (event.type === "stdin_pipe") {
        escapeCapture(event);
      } else if (show_logs) {
        if (show_logs && event.type === "pull_msg") {
          pullProgressBar(event);
        } else if (event.type === "action") {
          var keys = ["commands", "scale"];
          var actions = ["pull_image", "build_image"];

          if (actions.indexOf(event.action) > -1) {
            var data = { image: system.image.name };
            this.ui.ok([...keys].concat(event.action), data);
          }
        }
      }
    };
  }

  _parse_option(option, regex, split, fail, key_index = 0, format = null) {
    var result = {};
    for (var j = 0; j < option.length; j++) {
      var opt = option[j];
      if (opt.match(regex)) {
        opt = opt.split(split);
        result[opt[key_index]] = format ? format(opt) : opt[1];
      } else {
        this.ui.fail('commands.shell.' + fail, { value: opt });
        return 1;
      }
    }
    return result;
  }
}

module.exports = Shell;
<commit_msg>[cli] Sending `TERM` env if is not setted<commit_after>import { CliTrackerController } from 'azk/cli/cli_tracker_controller';
import { Helpers } from 'azk/cli/helpers';
import { _, config, lazy_require } from 'azk';
import { defer, asyncUnsubscribe } from 'azk/utils/promises';
import { subscribe } from 'azk/utils/postal';

var lazy = lazy_require({
  Manifest: ['azk/manifest'],
  docker  : ['azk/docker', 'default'],
});

class Shell extends CliTrackerController {
  index() {
    var { options } = this.normalized_params;
    var args = this.normalized_params.arguments;

    var _subscription = subscribe('docker.pull.status', (data) => {
      Helpers.newPullProgressBar(this.ui)(data);
    });

    return asyncUnsubscribe(this, _subscription, function* () {
      var dir = this.cwd;
      var manifest, system;

      yield Helpers.requireAgent(this.ui);

      if (options.image) {
        // Arbitrary image
        manifest = lazy.Manifest.makeFake(dir, options.image);
        system   = manifest.systemDefault;
      } else {
        manifest = new lazy.Manifest(dir, true);
        Helpers.manifestValidate(this.ui, manifest);

        system   = manifest.systemDefault;
        if (args.system) {
          system = manifest.system(args.system, true);
        }
      }

      if (_.isString(options.command)) {
        options.command = `${options.command};`;
      }
      var commands = _.compact([ options.command, ...args['shell-args']]);
      var tty_default = options.tty || _.isEmpty(commands);
      var tty = (options['no-tty']) ? (options.tty || false) : tty_default;

      var stdin = this.ui.stdin();
      stdin.custom_pipe = () => { };

      var cmd_options  = {
        interactive: tty,
        pull   : this.ui.stdout(),
        stdout : this.ui.stdout(),
        stderr : this.ui.stderr(),
        stdin  : stdin,
        workdir: options.cwd || null,
      };

      // Support extra envs, ports and mount volumes
      cmd_options.envs   = this._parse_option(options.env  , /.+=.+/, '=', 'invalid_env');
      if (!cmd_options.envs.TERM) {
        cmd_options.envs.TERM = process.env.TERM;
      }
      cmd_options.mounts = this._parse_option(options.mount, /.+:.+:?.*/, ':', 'invalid_mount', 1, (opts) => {
        return { type: (opts[2] ? opts[1] : 'path'), value: (opts[2] ? opts[2] : opts[0]) };
      });

      // TODO add support to `-- [shell-args]`
      var cmd = [options.shell || system.shell];
      if (!_.isEmpty(commands)) {
        cmd.push("-c");
        cmd.push(commands.join(' '));
      }
      cmd = _.compact(cmd);

      // Remove container before run
      var is_remove = !options['no-remove'] ? config("docker:remove_container") : !options['no-remove'];
      cmd_options = _.merge(cmd_options, {
        build_force    : options.rebuild || false,
        provision_force: (options.rebuild ? true : options.reprovision) || false,
        remove         : is_remove,
      });

      var result = defer((resolver, reject) => {
        var escape = (key, container, next) => {
          if (key === ".") {
            process.nextTick(() => {
              lazy.docker.getContainer(container).stop({ t: 5000 }).catch(reject);
            });
            return true;
          } else if (key === "?") {
            this.ok("coming soon...");
            process.nextTick(() => next());
            return true;
          }
          return false;
        };

        var _subscription_run = subscribe('docker.run.status', (data) => {
          this._escapeAndPullProgress(escape, system,
            !options.silent, options.verbose, options.stdout)(data);
        });

        system
          .runShell(cmd, cmd_options)
          .then(function (result) {
            _subscription_run.unsubscribe();
            return result;
          })
          .then(resolver, reject)
          .catch(function (err) {
            _subscription_run.unsubscribe();
            throw err;
          });
      });

      result = yield result.catch((error) => {
        return this.parseError(error);
      });

      return result.code;
    });
  }

  parseError(error) {
    if (error.statusCode) {
      if (error.statusCode === 404 && error.reason === "no such container") {
        this.ui.fail("commands.shell.ended.removed");
        return { code: 127 };
      }
    } else if (error.code === 'ECONNRESET') {
      this.ui.fail("commands.shell.ended.docker_end");
      return { code: 127 };
    } else if (error.code === 'ECONNREFUSED') {
      this.ui.fail("commands.shell.ended.docker_not_found");
      return { code: 127 };
    }
    throw error;
  }

  _escapeAndPullProgress(escape, system, show_logs, verbose) {
    return (event) => {
      var pullProgressBar = Helpers.newPullProgressBar(this.ui);
      var escapeCapture   = Helpers.escapeCapture(escape);

      // show verbose output
      if (verbose && event.stream) {
        this.ui.stdout().write('  ' + event.stream);
      }

      if (event.type === "stdin_pipe") {
        escapeCapture(event);
      } else if (show_logs) {
        if (show_logs && event.type === "pull_msg") {
          pullProgressBar(event);
        } else if (event.type === "action") {
          var keys = ["commands", "scale"];
          var actions = ["pull_image", "build_image"];

          if (actions.indexOf(event.action) > -1) {
            var data = { image: system.image.name };
            this.ui.ok([...keys].concat(event.action), data);
          }
        }
      }
    };
  }

  _parse_option(option, regex, split, fail, key_index = 0, format = null) {
    var result = {};
    for (var j = 0; j < option.length; j++) {
      var opt = option[j];
      if (opt.match(regex)) {
        opt = opt.split(split);
        result[opt[key_index]] = format ? format(opt) : opt[1];
      } else {
        this.ui.fail('commands.shell.' + fail, { value: opt });
        return 1;
      }
    }
    return result;
  }
}

module.exports = Shell;
<|endoftext|>


<commit_before>/* Copyright 2015 Tosho Toshev

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License. */

(function() {
	var cloudFlarePurge = {
		currentUrl : null,
		currentTabId : null,
		promptElement : null,

		init : function() {
			var owner = this;

			this.promptElement = $("#lightbox");

			$("#purgeAllButton").on("click", function(e) {
				e.preventDefault();
				owner.purgeAllBtnClick();
			});

			$("#purgeButton").on("click", function(e) {
				e.preventDefault();
				owner.purgeBtnClick();
			});
		},

		promptNoClick: function() {
			this.promptElement.removeClass("active");
		},

		promptYesClick: function(yesAction, settings) {
			this.promptElement.removeClass("active");
			if(typeof yesAction === "function") {
				yesAction(settings.domain, settings.callback);
			}
		},

		showPrompt: function(yesAction, settings) {
			this.promptElement.addClass("active");
			var owner = this;

			$("#promptYes").on("click", function(e) {
				e.preventDefault();
				owner.promptYesClick(yesAction, settings);
			});

			$("#promptNo").on("click", function(e) {
				e.preventDefault();
				owner.promptNoClick();
			});
		},

		purgeAllBtnClick: function() {
			var owner = this;
			this.getCurrentTab(function(tab) {
				var regex = /^[a-zA-Z0-9]*\./i;
				var domain = owner.getDomain(owner.currentUrl);
			    domain = domain.replace(domain.match(regex)[0], "");

				var settings = { domain : domain,
						         callback : $.proxy(owner.purgeEntireCloudflareCache, owner)
				};

				owner.showPrompt($.proxy(owner.getCloudFlareZoneId, owner), settings);
			});
		},

		purgeBtnClick: function() {
			var owner = this;
			this.getCurrentTab(function(tab) {
				var regex = /^[a-zA-Z0-9]*\./i;
				var domain = owner.getDomain(owner.currentUrl);
			    domain = domain.replace(domain.match(regex)[0], "");
			    owner.getCloudFlareZoneId(domain, $.proxy(owner.purgeCloudFlareUrls, owner));
			});
		},

		getCurrentTab: function(callback) {
			var owner = this;
			var queryInfo = {
				active : true,
				currentWindow: true
			};

			chrome.tabs.query(queryInfo, function(tabs) {
				var tab = tabs[0];

				if(tab.url !== undefined) {
					owner.currentUrl = tab.url;
				}

				owner.currentTabId = tab.id;

				if(typeof callback === "function") {
					callback(tab);
				}
			});
		},

		getCloudFlareZoneId: function(domain, callback) {
			var owner = this;
			$("#purgeButton").attr("class", "loading");
			chrome.storage.sync.get({
				tag: "options",
                key: null,
                email: null,
				refresh: null
			},

			function(settings) {
				if(settings.refresh == undefined || settings.refresh == null || settings.refresh == "") {
					settings.refresh = 10;
				}

            	$.ajax({
					url: "https://api.cloudflare.com/client/v4/zones?name=" + domain + "&status=active",
					beforeSend: function(xhr) {
				        xhr.setRequestHeader('x-auth-Email', settings.email);
						xhr.setRequestHeader('x-auth-key', settings.key);
				    },
					crossDomain: true,
					contentType: "application/json",
					dataType: "json",
					success: function(data) {
						if(data.success == true && data.result[0]) {
							callback(data.result[0].id, settings);
							return;
						}

						$("#purgeButton").attr("class", "");
						$("#status").attr("class", "error");
						owner.setStatusMessage("#status", "PURGE FAILED", 3000);
					},
					error: function(err) {
						$("#purgeButton").attr("class", "");
						$("#status").attr("class", "error");
						owner.setStatusMessage("#status", "PURGE FAILED", 3000);
					}
				});
			});
		},

		purgeCloudFlareUrls: function(zoneId, settings) {
			var urls = [this.currentUrl];
			this.cloudFlareApiPurgeCache({ "files": urls }, zoneId, settings);
		},

		purgeEntireCloudflareCache: function(zoneId, settings) {
			this.cloudFlareApiPurgeCache({ "purge_everything": true }, zoneId, settings);
		},

		cloudFlareApiPurgeCache: function(data, zoneId, settings) {
			var owner = this;
			$.ajax({
					url: "https://api.cloudflare.com/client/v4/zones/" + zoneId + "/purge_cache",
					method: "DELETE",
					beforeSend: function(xhr) {
				        xhr.setRequestHeader('x-auth-Email', settings.email);
						xhr.setRequestHeader('x-auth-key', settings.key);
				    },
					data: JSON.stringify(data),
					crossDomain: true,
					contentType: "application/json",
					dataType: "json",
					success: function(data) {
						if(data.success == true && data.result) {
							owner.onPurgeSuccess(data.result.id, settings);
							return;
						}

						$("#purgeButton").attr("class", "");
						$("#status").attr("class", "error");
						owner.setStatusMessage("#status", "PURGE FAILED", 3000);
					},
					error: function(err) {
						$("#purgeButton").attr("class", "");
						$("#status").attr("class", "error");
						owner.setStatusMessage("#status", "PURGE FAILED", 3000);
					}
			});
		},

		onPurgeSuccess : function(id, settings) {
			$("#purgeButton").attr("class", "");
			$("#status").attr("class", "success");
			this.setStatusMessage("#status", "SUCCESS", 3000);
			if($("#refresh").is(":checked")) {
				this.refreshCountdown($("#sub-status"), "Refreshing in: ", parseInt(settings.refresh),
				function() {
					chrome.tabs.reload(this.currentTabId, { bypassCache : true });
				});
			}
		},

		setStatusMessage: function(element, message, timeout) {
			$(element).text(message);
			setTimeout(function() {
                $(element).text("");
            }, timeout);
		},

		refreshCountdown: function(element, message, refreshTimeout, callback) {
			var interval = setInterval(function() {
				if(refreshTimeout == 0) {
					clearInterval(interval);
					callback();
					element.text("");
					return;
				}

				refreshTimeout--;
				element.text(message + refreshTimeout);
			}, 1000);
		},

		getDomain : function(url) {
			   var domain;
			    if (url.indexOf("://") > -1) {
			        domain = url.split('/')[2];
			    }
			    else {
			        domain = url.split('/')[0];
			    }

			    domain = domain.split(':')[0];

			    return domain;
		}
	};

	cloudFlarePurge.init();
})();<commit_msg>Fix for URLs with anchor links<commit_after>/* Copyright 2015 Tosho Toshev

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License. */

(function() {
	var cloudFlarePurge = {
		currentUrl : null,
		currentTabId : null,
		promptElement : null,

		init : function() {
			var owner = this;

			this.promptElement = $("#lightbox");

			$("#purgeAllButton").on("click", function(e) {
				e.preventDefault();
				owner.purgeAllBtnClick();
			});

			$("#purgeButton").on("click", function(e) {
				e.preventDefault();
				owner.purgeBtnClick();
			});
		},

		promptNoClick: function() {
			this.promptElement.removeClass("active");
		},

		promptYesClick: function(yesAction, settings) {
			this.promptElement.removeClass("active");
			if(typeof yesAction === "function") {
				yesAction(settings.domain, settings.callback);
			}
		},

		showPrompt: function(yesAction, settings) {
			this.promptElement.addClass("active");
			var owner = this;

			$("#promptYes").on("click", function(e) {
				e.preventDefault();
				owner.promptYesClick(yesAction, settings);
			});

			$("#promptNo").on("click", function(e) {
				e.preventDefault();
				owner.promptNoClick();
			});
		},

		purgeAllBtnClick: function() {
			var owner = this;
			this.getCurrentTab(function(tab) {
				var regex = /^[a-zA-Z0-9]*\./i;
				var domain = owner.getDomain(owner.currentUrl);
			    domain = domain.replace(domain.match(regex)[0], "");

				var settings = { domain : domain,
						         callback : $.proxy(owner.purgeEntireCloudflareCache, owner)
				};

				owner.showPrompt($.proxy(owner.getCloudFlareZoneId, owner), settings);
			});
		},

		purgeBtnClick: function() {
			var owner = this;
			this.getCurrentTab(function(tab) {
				var regex = /^[a-zA-Z0-9]*\./i;
				var domain = owner.getDomain(owner.currentUrl);
			    domain = domain.replace(domain.match(regex)[0], "");
			    owner.getCloudFlareZoneId(domain, $.proxy(owner.purgeCloudFlareUrls, owner));
			});
		},

		getCurrentTab: function(callback) {
			var owner = this;
			var queryInfo = {
				active : true,
				currentWindow: true
			};

			chrome.tabs.query(queryInfo, function(tabs) {
				var tab = tabs[0];

				if(tab.url !== undefined) {
					owner.currentUrl = tab.url.split("#")[0];
				}

				owner.currentTabId = tab.id;

				if(typeof callback === "function") {
					callback(tab);
				}
			});
		},

		getCloudFlareZoneId: function(domain, callback) {
			var owner = this;
			$("#purgeButton").attr("class", "loading");
			chrome.storage.sync.get({
				tag: "options",
                key: null,
                email: null,
				refresh: null
			},

			function(settings) {
				if(settings.refresh == undefined || settings.refresh == null || settings.refresh == "") {
					settings.refresh = 10;
				}

            	$.ajax({
					url: "https://api.cloudflare.com/client/v4/zones?name=" + domain + "&status=active",
					beforeSend: function(xhr) {
				        xhr.setRequestHeader('x-auth-Email', settings.email);
						xhr.setRequestHeader('x-auth-key', settings.key);
				    },
					crossDomain: true,
					contentType: "application/json",
					dataType: "json",
					success: function(data) {
						if(data.success == true && data.result[0]) {
							callback(data.result[0].id, settings);
							return;
						}

						$("#purgeButton").attr("class", "");
						$("#status").attr("class", "error");
						owner.setStatusMessage("#status", "PURGE FAILED", 3000);
					},
					error: function(err) {
						$("#purgeButton").attr("class", "");
						$("#status").attr("class", "error");
						owner.setStatusMessage("#status", "PURGE FAILED", 3000);
					}
				});
			});
		},

		purgeCloudFlareUrls: function(zoneId, settings) {
			var urls = [this.currentUrl];
			this.cloudFlareApiPurgeCache({ "files": urls }, zoneId, settings);
		},

		purgeEntireCloudflareCache: function(zoneId, settings) {
			this.cloudFlareApiPurgeCache({ "purge_everything": true }, zoneId, settings);
		},

		cloudFlareApiPurgeCache: function(data, zoneId, settings) {
			var owner = this;
			$.ajax({
					url: "https://api.cloudflare.com/client/v4/zones/" + zoneId + "/purge_cache",
					method: "DELETE",
					beforeSend: function(xhr) {
				        xhr.setRequestHeader('x-auth-Email', settings.email);
						xhr.setRequestHeader('x-auth-key', settings.key);
				    },
					data: JSON.stringify(data),
					crossDomain: true,
					contentType: "application/json",
					dataType: "json",
					success: function(data) {
						if(data.success == true && data.result) {
							owner.onPurgeSuccess(data.result.id, settings);
							return;
						}

						$("#purgeButton").attr("class", "");
						$("#status").attr("class", "error");
						owner.setStatusMessage("#status", "PURGE FAILED", 3000);
					},
					error: function(err) {
						$("#purgeButton").attr("class", "");
						$("#status").attr("class", "error");
						owner.setStatusMessage("#status", "PURGE FAILED", 3000);
					}
			});
		},

		onPurgeSuccess : function(id, settings) {
			$("#purgeButton").attr("class", "");
			$("#status").attr("class", "success");
			this.setStatusMessage("#status", "SUCCESS", 3000);
			if($("#refresh").is(":checked")) {
				this.refreshCountdown($("#sub-status"), "Refreshing in: ", parseInt(settings.refresh),
				function() {
					chrome.tabs.reload(this.currentTabId, { bypassCache : true });
				});
			}
		},

		setStatusMessage: function(element, message, timeout) {
			$(element).text(message);
			setTimeout(function() {
                $(element).text("");
            }, timeout);
		},

		refreshCountdown: function(element, message, refreshTimeout, callback) {
			var interval = setInterval(function() {
				if(refreshTimeout == 0) {
					clearInterval(interval);
					callback();
					element.text("");
					return;
				}

				refreshTimeout--;
				element.text(message + refreshTimeout);
			}, 1000);
		},

		getDomain : function(url) {
			   var domain;
			    if (url.indexOf("://") > -1) {
			        domain = url.split('/')[2];
			    }
			    else {
			        domain = url.split('/')[0];
			    }

			    domain = domain.split(':')[0];

			    return domain;
		}
	};

	cloudFlarePurge.init();
})();<|endoftext|>