function makeNetworkFromIds($depth)
{
    global $apikey, $nodes, $edges, $ids, $crawldepth;
    echo "<br /><br />getting details for " . count($ids) . " videos at depth " . $depth . ": ";
    $newids = array();
    $categoryIds = array();
    for ($i = 0; $i < count($ids); $i++) {
        $vid = $ids[$i];
        $restquery = "https://www.googleapis.com/youtube/v3/videos?part=statistics,contentDetails,snippet&id=" . $vid . "&key=" . $apikey;
        $reply = doAPIRequest($restquery);
        if (isset($reply->items[0])) {
            $video = $reply->items[0];
            // collect categories
            if (!in_array($video->snippet->categoryId, $categoryIds)) {
                $categoryIds[] = $video->snippet->categoryId;
            }
            $row = array();
            $row["channelId"] = $video->snippet->channelId;
            $row["channelTitle"] = preg_replace("/\\s+/", " ", $video->snippet->channelTitle);
            $row["videoId"] = $video->id;
            $row["publishedAt"] = strtotime($video->snippet->publishedAt);
            $row["videoTitle"] = preg_replace("/\\s+/", " ", $video->snippet->title);
            $row["videoDescription"] = preg_replace("/\\s+/", " ", $video->snippet->description);
            $row["videoCategoryId"] = $video->snippet->categoryId;
            $row["videoCategoryLabel"] = "";
            $row["duration"] = $video->contentDetails->duration;
            $row["dimension"] = $video->contentDetails->dimension;
            $row["definition"] = $video->contentDetails->definition;
            $row["caption"] = $video->contentDetails->caption;
            $row["licensedContent"] = $video->contentDetails->licensedContent;
            $row["viewCount"] = $video->statistics->viewCount;
            $row["likeCount"] = $video->statistics->likeCount;
            $row["dislikeCount"] = $video->statistics->dislikeCount;
            $row["favoriteCount"] = $video->statistics->favoriteCount;
            $row["commentCount"] = $video->statistics->commentCount;
            $nodes[$vid] = $row;
            if ($depth == 0) {
                $nodes[$vid]["isSeed"] = "yes";
                $nodes[$vid]["seedRank"] = $i + 1;
            } else {
                $nodes[$vid]["isSeed"] = "no";
                $nodes[$vid]["seedRank"] = "";
            }
        }
        echo $i . " ";
        flush();
        ob_flush();
    }
    // get category labels and assign to videos
    $restquery = "https://www.googleapis.com/youtube/v3/videoCategories?part=snippet&id=" . urlencode(implode(",", $categoryIds)) . "&key=" . $apikey;
    $reply = doAPIRequest($restquery);
    $categoryTrans = array();
    foreach ($reply->items as $cat) {
        $categoryTrans[$cat->id] = $cat->snippet->title;
    }
    foreach ($nodes as $key => $node) {
        $nodes[$key]["videoCategoryLabel"] = $categoryTrans[$node["videoCategoryId"]];
    }
    echo "<br />getting related videos for " . count($ids) . " videos at depth " . $depth . ": ";
    for ($i = 0; $i < count($ids); $i++) {
        $vid = $ids[$i];
        // get related videos
        $run = true;
        $nextpagetoken = null;
        while ($run == true) {
            $restquery = "https://www.googleapis.com/youtube/v3/search?part=id&maxResults=50&relatedToVideoId=" . $vid . "&type=video&key=" . $apikey;
            if ($nextpagetoken != null) {
                $restquery .= "&pageToken=" . $nextpagetoken;
            }
            $reply = doAPIRequest($restquery);
            foreach ($reply->items as $item) {
                $featid = $item->id->videoId;
                if (!isset($nodes[$featid])) {
                    if (!in_array($featid, $newids)) {
                        $newids[] = $featid;
                    }
                    if ($depth < $crawldepth) {
                        $edgeid = $vid . "_|_|X|_|_" . $featid;
                        $edges[$edgeid] = true;
                    }
                } else {
                    $edgeid = $vid . "_|_|X|_|_" . $featid;
                    $edges[$edgeid] = true;
                }
            }
            if (isset($reply->nextPageToken) && $reply->nextPageToken != "") {
                $nextpagetoken = $reply->nextPageToken;
            } else {
                $run = false;
            }
        }
        echo $i . " ";
        flush();
        ob_flush();
    }
    if ($depth == $crawldepth) {
        //print_r($nodes); exit;
        renderNetwork();
    } else {
        //print_r($newids);
        $ids = $newids;
        $depth++;
        makeNetworkFromIds($depth);
    }
}
function makeNetworkFromIds($depth)
{
    global $apikey, $nodes, $edges, $ids, $crawldepth, $subscriptions;
    echo "<br /><br />getting details for " . count($ids) . " channels at depth " . $depth . ": ";
    $newids = array();
    for ($i = 0; $i < count($ids); $i++) {
        $chid = $ids[$i];
        //$restquery = "https://www.googleapis.com/youtube/v3/channels?part=brandingSettings,status,id,snippet,contentDetails,contentOwnerDetails,statistics,topicDetails,invideoPromotion&id=".$chid."&key=".$apikey;
        $restquery = "https://www.googleapis.com/youtube/v3/channels?part=brandingSettings,id,snippet,statistics&id=" . $chid . "&key=" . $apikey;
        $reply = doAPIRequest($restquery);
        //print_r($reply);
        if (isset($reply->items[0])) {
            $nodes[$chid] = $reply->items[0];
            $nodes[$chid]->done = false;
            if ($depth == 0) {
                $nodes[$chid]->isSeed = "yes";
                $nodes[$chid]->seedRank = $i + 1;
            } else {
                $nodes[$chid]->isSeed = "no";
                $nodes[$chid]->seedRank = "";
            }
        }
        echo $i . " ";
        flush();
        ob_flush();
    }
    //print_r($nodes);
    if ($subscriptions == "on") {
        echo "<br />getting subscriptions for " . count($ids) . " channels at depth " . $depth . ": ";
        $counter = 0;
    }
    foreach ($nodes as $nodeid => $nodedata) {
        if (isset($nodedata->brandingSettings->channel->featuredChannelsUrls)) {
            foreach ($nodedata->brandingSettings->channel->featuredChannelsUrls as $featid) {
                if (!isset($nodes[$featid])) {
                    if (!in_array($featid, $newids)) {
                        $newids[] = $featid;
                    }
                    if ($depth < $crawldepth) {
                        $edgeid = $nodeid . "_|_|X|_|_" . $featid;
                        $edges[$edgeid] = true;
                    }
                } else {
                    $edgeid = $nodeid . "_|_|X|_|_" . $featid;
                    $edges[$edgeid] = true;
                }
            }
        }
        if ($subscriptions == "on" && $nodedata->done == false) {
            $run = true;
            $nextpagetoken = null;
            echo $counter . " ";
            flush();
            ob_flush();
            $counter++;
            while ($run == true) {
                $restquery = "https://www.googleapis.com/youtube/v3/subscriptions?part=snippet&channelId=" . $nodedata->id . "&maxResults=50&key=" . $apikey;
                if ($nextpagetoken != null) {
                    $restquery .= "&pageToken=" . $nextpagetoken;
                }
                $reply = doAPIRequest($restquery);
                //print_r($reply); exit;
                foreach ($reply->items as $item) {
                    $featid = $item->snippet->resourceId->channelId;
                    //print_r($item);
                    if (!isset($nodes[$featid])) {
                        if (!in_array($featid, $newids)) {
                            $newids[] = $featid;
                        }
                        if ($depth < $crawldepth) {
                            $edgeid = $nodeid . "_|_|X|_|_" . $featid;
                            $edges[$edgeid] = true;
                        }
                    } else {
                        $edgeid = $nodeid . "_|_|X|_|_" . $featid;
                        $edges[$edgeid] = true;
                    }
                }
                if (isset($reply->nextPageToken) && $reply->nextPageToken != "") {
                    $nextpagetoken = $reply->nextPageToken;
                } else {
                    $run = false;
                }
            }
            $nodes[$nodeid]->done = true;
        }
        //print_r($newids);
    }
    if ($depth == $crawldepth) {
        renderNetwork();
    } else {
        $ids = $newids;
        $depth++;
        makeNetworkFromIds($depth);
    }
}