handle

in api-reference-examples/ruby/te-tag-query/TETagQuery.rb [435:566]


  def handle(args, options)
    options['includeIndicatorInOutput'] = true
    options['pageSize'] = 10

    loop do
      break if args.length == 0
      break unless args[0][0] == '-'
      option = args.shift

      if option == '-h'
        self.usage(0)
      elsif option == '--help'
        self.usage(0)

      elsif option == '--tagged-since'
        self.usage(1) unless args.length >= 1
        options['taggedSince'] = args.shift;
      elsif option == '--tagged-until'
        self.usage(1) unless args.length >= 1
        options['taggedUntil'] = args.shift;

      elsif option == '--created-since'
        self.usage(1) unless args.length >= 1
        options['createdSince'] = args.shift;
      elsif option == '--created-until'
        self.usage(1) unless args.length >= 1
        options['createdUntil'] = args.shift;

      elsif option == '--page-size'
        self.usage(1) unless args.length >= 1
        options['pageSize'] = args.shift;
      elsif option == '--no-print-indicator'
        self.usage(1) unless args.length >= 1
        options['includeIndicatorInOutput'] = false

      else
        $stderr.puts "#{$0} #{@verbName}: unrecognized  option #{option}"
        exit 1
      end
    end

    # Tagged-at filtering is done server-side -- the TE /tagged_objects
    # endpoint filters by tagged-at timestamps on the graph edges from tag to
    # descriptor ID. An implementation detail of /tagged_objects is that it
    # only yields abstract IDs; descriptor IDs to details are a separate pass
    # in this design.
    #
    # This means that if the user wants to filter on created-at:
    # * We have the invariants that created-at <= tagged-at, and tagged-at <= now.
    # * If they ask for created-since t, we query the server for tagged-since t
    #   (which overfetches) and then we filter client-side.
    # * If they as for created-until t, we query the server for tagged-until now
    #   (which overfetches) and then we filter client-side.
    options['createdSinceEpochSeconds'] = nil
    options['createdUntilEpochSeconds'] = nil
    if options['createdSince'] != nil
      if options['taggedSince'] != nil
        $stderr.puts "#{$0} #{@verbName}: Please specify at most one of --tagged-since and --created-since."
        exit 1
      end
      options['taggedSince'] = options['createdSince']
      options['createdSinceEpochSeconds'] = ThreatExchange::TENet::parseTimeStringToEpochSeconds(options['createdSince'])
    end
    if options['createdUntil'] != nil
      if options['taggedUntil'] != nil
        $stderr.puts "#{$0} #{@verbName}: Please specify at most one of --tagged-until and --created-until."
        exit 1
      end
      # keep options['taggedUntil'] = nil
      options['createdUntilEpochSeconds'] = ThreatExchange::TENet::parseTimeStringToEpochSeconds(options['createdUntil'])
    end

    if args.length != 1
      self.usage(1)
    end
    tagName = args[0]

    # Step 1: tag text to ID
    # Step 2: tag ID to descriptor IDs, paginated
    # Step 3: descriptor IDs to descriptor details, paginated

    puts("TAG_NAME=#{tagName}")
    tag_id = ThreatExchange::TENet::getTagIDFromName(
      tagName,
      showURLs: options['showURLs'],
    )

    idProcessor = lambda do |idBatch|
      descriptors = ThreatExchange::TENet.getInfoForIDs(
        idBatch,
        verbose: options['verbose'],
        showURLs: options['showURLs'],
        includeIndicatorInOutput: options['includeIndicatorInOutput'])

      createdSinceEpochSeconds = options['createdSinceEpochSeconds']
      createdUntilEpochSeconds = options['createdUntilEpochSeconds']

      descriptors.each do |descriptor|
        added_on = descriptor['added_on']
        if added_on.nil?
          puts("WTFA")
          puts(descriptor)
          puts("WTFB")
        end
        descriptorCreatedAtEpochSeconds = ThreatExchange::TENet::parseTimeStringToEpochSeconds(added_on)
        if createdSinceEpochSeconds != nil
          if descriptorCreatedAtEpochSeconds < createdSinceEpochSeconds
            next
          end
        end
        if createdUntilEpochSeconds != nil
          if descriptorCreatedAtEpochSeconds > createdUntilEpochSeconds
            next
          end
        end

        # Stub processing -- one would perhaps integrate with one's own system
        puts descriptor.to_json
      end
    end

    ThreatExchange::TENet::processDescriptorIDsByTagID(
      tag_id,
      verbose: options['verbose'],
      showURLs: options['showURLs'],
      taggedSince: options['taggedSince'],
      taggedUntil: options['taggedUntil'],
      pageSize: options['pageSize'],
      includeIndicatorInOutput: options['includeIndicatorInOutput'],
      idProcessor: idProcessor)
  end