nodes: 0, module; 1, function_definition; 2, function_name:dispatchlist; 3, parameters; 4, block; 5, identifier:self; 6, keyword_separator; 7, default_parameter; 8, default_parameter; 9, default_parameter; 10, default_parameter; 11, expression_statement; 12, expression_statement; 13, if_statement; 14, comment:# Here we do need to ensure that our categories are valid, cause; 15, comment:# NS just ignores the categories it doesn't recognise and returns; 16, comment:# whatever it feels like.; 17, if_statement; 18, decorated_definition; 19, return_statement; 20, identifier:author; 21, None; 22, identifier:category; 23, None; 24, identifier:subcategory; 25, None; 26, identifier:sort; 27, string; 28, comment:"""Find dispatches by certain criteria.
  
          Parameters
          ----------
          author : str
              Name of the nation authoring the dispatch.
          category : str
              Dispatch's primary category.
          subcategory : str
              Dispatch's secondary category.
          sort : str
              Sort order, 'new' or 'best'.
  
          Returns
          -------
          an :class:`ApiQuery` of a list of :class:`DispatchThumbnail`
          """; 29, assignment; 30, identifier:author; 31, block; 32, boolean_operator; 33, block; 34, elif_clause; 35, else_clause; 36, decorator; 37, function_definition; 38, call; 39, string_content:new; 40, identifier:params; 41, dictionary; 42, expression_statement; 43, identifier:category; 44, identifier:subcategory; 45, if_statement; 46, expression_statement; 47, identifier:category; 48, block; 49, block; 50, call; 51, function_name:result; 52, parameters; 53, block; 54, identifier:result; 55, argument_list; 56, pair; 57, assignment; 58, parenthesized_expression; 59, block; 60, assignment; 61, if_statement; 62, expression_statement; 63, raise_statement; 64, identifier:api_query; 65, argument_list; 66, identifier:_; 67, identifier:root; 68, return_statement; 69, identifier:self; 70, string; 71, identifier:sort; 72, subscript; 73, identifier:author; 74, boolean_operator; 75, raise_statement; 76, subscript; 77, string; 78, comparison_operator:category not in dispatch_categories; 79, block; 80, assignment; 81, call; 82, string; 83, dictionary_splat; 84, list_comprehension; 85, string_content:sort; 86, identifier:params; 87, string; 88, comparison_operator:category not in dispatch_categories; 89, comparison_operator:subcategory not in dispatch_categories[category]; 90, call; 91, identifier:params; 92, string; 93, interpolation; 94, string_content::; 95, interpolation; 96, identifier:category; 97, identifier:dispatch_categories; 98, raise_statement; 99, subscript; 100, identifier:category; 101, identifier:ValueError; 102, argument_list; 103, string_content:dispatchlist; 104, identifier:params; 105, call; 106, for_in_clause; 107, string_content:dispatchauthor; 108, identifier:category; 109, identifier:dispatch_categories; 110, identifier:subcategory; 111, subscript; 112, identifier:ValueError; 113, argument_list; 114, string_content:dispatchcategory; 115, identifier:category; 116, identifier:subcategory; 117, call; 118, identifier:params; 119, string; 120, string; 121, attribute; 122, argument_list; 123, identifier:elem; 124, call; 125, identifier:dispatch_categories; 126, identifier:category; 127, string; 128, identifier:ValueError; 129, argument_list; 130, string_content:dispatchcategory; 131, string_content:Cannot request subcategory without category; 132, identifier:DispatchThumbnail; 133, identifier:_from_elem; 134, identifier:elem; 135, attribute; 136, argument_list; 137, string_content:Invalid category/subcategory; 138, string; 139, identifier:root; 140, identifier:find; 141, string; 142, string_content:Invalid category; 143, string_content:DISPATCHLIST
code: def dispatchlist(self, *, author=None, category=None,
                       subcategory=None, sort='new'):
          """Find dispatches by certain criteria.
  
          Parameters
          ----------
          author : str
              Name of the nation authoring the dispatch.
          category : str
              Dispatch's primary category.
          subcategory : str
              Dispatch's secondary category.
          sort : str
              Sort order, 'new' or 'best'.
  
          Returns
          -------
          an :class:`ApiQuery` of a list of :class:`DispatchThumbnail`
          """
          params = {'sort': sort}
          if author:
              params['dispatchauthor'] = author
          # Here we do need to ensure that our categories are valid, cause
          # NS just ignores the categories it doesn't recognise and returns
          # whatever it feels like.
          if category and subcategory:
              if (category not in dispatch_categories or
                      subcategory not in dispatch_categories[category]):
                  raise ValueError('Invalid category/subcategory')
              params['dispatchcategory'] = f'{category}:{subcategory}'
          elif category:
              if category not in dispatch_categories:
                  raise ValueError('Invalid category')
              params['dispatchcategory'] = category
          else:
              raise ValueError('Cannot request subcategory without category')
  
          @api_query('dispatchlist', **params)
          async def result(_, root):
              return [
                  DispatchThumbnail._from_elem(elem)
                  for elem in root.find('DISPATCHLIST')
              ]
          return result(self)