Annotation of sbbs/src/sbbs3/gtkmonitor/gtkmonitor.c, revision 1.1

1.1     ! root        1: #include "dirwrap.h"
        !             2: #include "ini_file.h"
        !             3: 
        !             4: #include "events.h"
        !             5: #include "gtkmonitor.h"
        !             6: 
        !             7: scfg_t         cfg;
        !             8: GladeXML       *xml;
        !             9: int                    nodes=0;
        !            10: GtkListStore   *store = NULL;
        !            11: GtkTreeSelection *sel;
        !            12: struct gtkmonitor_config gtkm_conf;
        !            13: char                   glade_path[MAX_PATH+1];
        !            14: 
        !            15: void read_ini(void)
        !            16: {
        !            17:        FILE    *inif;
        !            18:        char    path[MAX_PATH+1];
        !            19: 
        !            20:        complete_path(path, cfg.ctrl_dir, "gtkmonitor.ini");
        !            21:        inif=fopen(path, "r");
        !            22:        iniReadString(inif, "commands", "ViewStdOut", "%f | xmessage -file -", gtkm_conf.view_stdout);
        !            23:        iniReadString(inif, "commands", "ViewTextFile", "xmessage -file %f", gtkm_conf.view_text_file);
        !            24:        iniReadString(inif, "commands", "EditTextFile", "xedit %f",gtkm_conf.edit_text_file);
        !            25:        iniReadString(inif, "commands", "ViewCtrlAFile", "%!asc2ans %f | %!syncview -l",gtkm_conf.view_ctrla_file);
        !            26:        iniReadString(inif, "commands", "ViewHTMLFile", "firefox file://%f", gtkm_conf.view_html_file);
        !            27:        if(inif)
        !            28:                fclose(inif);
        !            29:        else
        !            30:                write_ini();
        !            31: }
        !            32: 
        !            33: void write_ini(void)
        !            34: {
        !            35:        FILE    *inif;
        !            36:        char    path[MAX_PATH+1];
        !            37:        str_list_t      inifile;
        !            38: 
        !            39:        complete_path(path, cfg.ctrl_dir, "gtkmonitor.ini");
        !            40:        inif=fopen(path, "r");
        !            41:        if(inif) {
        !            42:                inifile=iniReadFile(inif);
        !            43:                fclose(inif);
        !            44:        }
        !            45:        else
        !            46:                inifile=strListInit();
        !            47:        iniSetString(&inifile, "commands", "ViewStdOut", gtkm_conf.view_stdout, NULL);
        !            48:        iniSetString(&inifile, "commands", "ViewTextFile", gtkm_conf.view_text_file, NULL);
        !            49:        iniSetString(&inifile, "commands", "EditTextFile", gtkm_conf.edit_text_file, NULL);
        !            50:        iniSetString(&inifile, "commands", "ViewCtrlAFile", gtkm_conf.view_ctrla_file, NULL);
        !            51:        iniSetString(&inifile, "commands", "ViewHTMLFile", gtkm_conf.view_html_file, NULL);
        !            52:        inif=fopen(path, "w");
        !            53:        if(inif) {
        !            54:                iniWriteFile(inif, inifile);
        !            55:                fclose(inif);
        !            56:        }
        !            57:        else
        !            58:                display_message("Cannot Create .ini File","Unable to create the .ini file.  Check your permissions.","gtk-dialog-error");
        !            59:        strListFree(&inifile);
        !            60: }
        !            61: 
        !            62: void refresh_events(void)
        !            63: {
        !            64:        int             i;
        !            65:        GtkWidget       *w;
        !            66:        GtkWidget       *menu;
        !            67:        char    str[1024];
        !            68:        char    flags[33];
        !            69: 
        !            70:     /* Read .cfg files here */
        !            71:        free_cfg(&cfg);
        !            72:     if(!load_cfg(&cfg, NULL, TRUE, str)) {
        !            73:                display_message("Load Error","Cannot load configuration data","gtk-dialog-error");
        !            74:         return;
        !            75:        }
        !            76: 
        !            77:        /* Update timed events */
        !            78:        w=glade_xml_get_widget(xml, "force_timed_event1");
        !            79:        if(w==NULL)
        !            80:                fprintf(stderr,"Cannot get timed event widget\n");
        !            81:        else {
        !            82:                menu=gtk_menu_item_get_submenu(GTK_MENU_ITEM(w));
        !            83:                gtk_widget_destroy(GTK_WIDGET(menu));
        !            84:                menu=gtk_menu_new();
        !            85:                gtk_menu_item_set_submenu (GTK_MENU_ITEM (w), menu);
        !            86:                if(menu!=NULL) {
        !            87:                        for(i=0; i<cfg.total_events; i++) {
        !            88:                                w = gtk_menu_item_new_with_label(cfg.event[i]->code);
        !            89:                                gtk_widget_show (w);
        !            90:                                gtk_container_add (GTK_CONTAINER (menu), w);
        !            91:                                g_signal_connect ((gpointer) w, "activate"
        !            92:                                                ,G_CALLBACK (on_force_event)
        !            93:                                                ,NULL);
        !            94:                        }
        !            95:                }
        !            96:                else
        !            97:                        fprintf(stderr,"Cannot get timed event submenu\n");
        !            98:        }
        !            99: 
        !           100:        /* Update network call-outs */
        !           101:        w=glade_xml_get_widget(xml, "force_network_callout1");
        !           102:        if(w==NULL)
        !           103:                fprintf(stderr,"Cannot get network callout widget\n");
        !           104:        else {
        !           105:                menu=gtk_menu_item_get_submenu(GTK_MENU_ITEM(w));
        !           106:                gtk_widget_destroy(GTK_WIDGET(menu));
        !           107:                menu=gtk_menu_new();
        !           108:                gtk_menu_item_set_submenu (GTK_MENU_ITEM (w), menu);
        !           109:                if(menu!=NULL) {
        !           110:                        for(i=0; i<cfg.total_qhubs; i++) {
        !           111:                                w = gtk_menu_item_new_with_label(cfg.qhub[i]->id);
        !           112:                                gtk_widget_show (w);
        !           113:                                gtk_container_add (GTK_CONTAINER (menu), w);
        !           114:                                g_signal_connect ((gpointer) w, "activate"
        !           115:                                                ,G_CALLBACK (on_force_qnet)
        !           116:                                                ,NULL);
        !           117:                        }
        !           118:                }
        !           119:                else
        !           120:                        fprintf(stderr,"Cannot get timed event submenu\n");
        !           121:        }
        !           122:        refresh_data(NULL);
        !           123: 
        !           124:        /* Set up quick validation values */
        !           125:        w=glade_xml_get_widget(xml, "cNodeQuickValidate");
        !           126:        for(i=0; i<=10; i++)
        !           127:                gtk_combo_box_remove_text(GTK_COMBO_BOX(w),0);
        !           128:        gtk_combo_box_append_text(GTK_COMBO_BOX(w), "Quick Validation Sets");
        !           129:        gtk_combo_box_set_active(GTK_COMBO_BOX(w), 0);
        !           130:        for(i=0;i<10;i++) {
        !           131:                sprintf(str,"%d  SL: %-2d  F1: %s",i,cfg.val_level[i],ltoaf(cfg.val_flags1[i],flags));
        !           132:                gtk_combo_box_append_text(GTK_COMBO_BOX(w), str);
        !           133:        }
        !           134: }
        !           135: 
        !           136: void add_to_stats(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
        !           137: {
        !           138:        stats_t *nstats=data;
        !           139:        stats_t stats;
        !           140:        gchar   *node;
        !           141: 
        !           142:        gtk_tree_model_get(model, iter, 0, &node, -1);
        !           143:        getstats(&cfg, atoi(node), &stats);
        !           144:        nstats->logons+=stats.logons;
        !           145:        nstats->ltoday+=stats.ltoday;
        !           146:        nstats->timeon+=stats.timeon;
        !           147:        nstats->ttoday+=stats.ttoday;
        !           148:        nstats->uls+=stats.uls;
        !           149:        nstats->ulb+=stats.ulb;
        !           150:        nstats->dls+=stats.dls;
        !           151:        nstats->dlb+=stats.dlb;
        !           152:        nstats->ptoday+=stats.ptoday;
        !           153:        nstats->etoday+=stats.etoday;
        !           154:        nstats->ftoday+=stats.ftoday;
        !           155:        nstats->nusers+=stats.nusers;
        !           156: }
        !           157: 
        !           158: /* Refreshes global variables... ie: Number of users */
        !           159: int refresh_data(gpointer data)
        !           160: {
        !           161:        char            str[1024];
        !           162:        char            str2[1024];
        !           163:        char            str3[1024];
        !           164:        char            *p;
        !           165:        GtkWidget       *w;
        !           166:        int                     i,j;
        !           167:        GtkTreeIter     curr;
        !           168:        GtkTreeModel    *model;
        !           169:        node_t  node;
        !           170:        stats_t sstats;
        !           171:        stats_t nstats;
        !           172:        stats_t stats;
        !           173:        int             shownodes;
        !           174: 
        !           175:        /* Update the node list stuff */
        !           176:        w=glade_xml_get_widget(xml, "lNodeList");
        !           177: 
        !           178:        /* Fist call... set up grid */
        !           179:        if(store == NULL) {
        !           180:                store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
        !           181:                gtk_tree_view_set_model(GTK_TREE_VIEW(w), GTK_TREE_MODEL(store));
        !           182:                gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(w), 0, "Node", gtk_cell_renderer_text_new(), "text", 0, NULL);
        !           183:                gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(w), 1, "Status", gtk_cell_renderer_text_new(), "text", 1, NULL);
        !           184:                nodes=0;
        !           185:                sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (w));
        !           186:                gtk_tree_selection_set_mode (sel, GTK_SELECTION_MULTIPLE);
        !           187:                g_signal_connect (G_OBJECT (sel), "changed", G_CALLBACK (update_stats_callback), NULL);
        !           188:        }
        !           189:        else
        !           190:                gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &curr);
        !           191: 
        !           192:        for(i=1; i<=cfg.sys_nodes; i++) {
        !           193:                if(i > nodes) {
        !           194:                        gtk_list_store_insert(store, &curr, i-1);
        !           195:                        sprintf(str,"%d",i);
        !           196:                        gtk_list_store_set(store, &curr, 0, str, -1);
        !           197:                        nodes++;
        !           198:                }
        !           199: 
        !           200:                if((j=getnodedat(&cfg,i,&node,NULL)))
        !           201:                        sprintf(str,"Error reading node data (%d)!",j);
        !           202:                else
        !           203:                        nodestatus(&cfg,&node,str,1023);
        !           204:                gtk_list_store_set(store, &curr, 1, str, -1);
        !           205:                gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &curr);
        !           206:        }
        !           207:        if(nodes >= i) {
        !           208:                for(i=nodes; i<=cfg.sys_nodes; i--) {
        !           209:                        gtk_list_store_remove(store, &curr);
        !           210:                        nodes--;
        !           211:                }
        !           212:        }
        !           213: 
        !           214:        getstats(&cfg, 0, &sstats);
        !           215: 
        !           216:        shownodes=gtk_tree_selection_count_selected_rows(sel);
        !           217:        if(shownodes) {
        !           218:                memset(&nstats, 0, sizeof(nstats));
        !           219:                gtk_tree_selection_selected_foreach(sel
        !           220:                                ,add_to_stats
        !           221:                                ,&nstats);
        !           222:        }
        !           223: 
        !           224:        w=glade_xml_get_widget(xml,"locknodebutton");
        !           225:        gtk_widget_set_sensitive(w, shownodes>0);
        !           226:        w=glade_xml_get_widget(xml,"downnodebutton");
        !           227:        gtk_widget_set_sensitive(w, shownodes>0);
        !           228:        w=glade_xml_get_widget(xml,"interruptnodebutton");
        !           229:        gtk_widget_set_sensitive(w, shownodes>0);
        !           230:        w=glade_xml_get_widget(xml,"bRerunNode");
        !           231:        gtk_widget_set_sensitive(w, shownodes>0);
        !           232:        w=glade_xml_get_widget(xml,"bRerunNode");
        !           233:        gtk_widget_set_sensitive(w, shownodes>0);
        !           234:        w=glade_xml_get_widget(xml,"bClearErrors");
        !           235:        gtk_widget_set_sensitive(w, shownodes>0);
        !           236:        if(shownodes==1) {
        !           237:                gtk_tree_selection_selected_foreach(sel
        !           238:                                ,get_lastselected_node
        !           239:                                ,&i);
        !           240:                if((j=getnodedat(&cfg,i,&node,NULL))) {
        !           241:                        sprintf(str,"Error reading node data (%d)!",j);
        !           242:                        node.status=NODE_WFC;
        !           243:                }
        !           244:                j=(node.status==NODE_QUIET || node.status==NODE_INUSE);
        !           245: 
        !           246:                w=glade_xml_get_widget(xml,"bChatWithUser");
        !           247:                gtk_widget_set_sensitive(w, j);
        !           248:                w=glade_xml_get_widget(xml,"bSendMessageToUser");
        !           249:                gtk_widget_set_sensitive(w, j);
        !           250:                w=glade_xml_get_widget(xml,"bEditUser");
        !           251:                gtk_widget_set_sensitive(w, j);
        !           252:                w=glade_xml_get_widget(xml,"cNodeQuickValidate");
        !           253:                gtk_widget_set_sensitive(w, j);
        !           254:        }
        !           255:        else {
        !           256:                w=glade_xml_get_widget(xml,"bChatWithUser");
        !           257:                gtk_widget_set_sensitive(w, FALSE);
        !           258:                w=glade_xml_get_widget(xml,"bSendMessageToUser");
        !           259:                gtk_widget_set_sensitive(w, FALSE);
        !           260:                w=glade_xml_get_widget(xml,"bEditUser");
        !           261:                gtk_widget_set_sensitive(w, FALSE);
        !           262:                w=glade_xml_get_widget(xml,"cNodeQuickValidate");
        !           263:                gtk_widget_set_sensitive(w, FALSE);
        !           264:        }
        !           265: 
        !           266:        w=glade_xml_get_widget(xml, "eLogonsToday");
        !           267:        if(w==NULL)
        !           268:                fprintf(stderr,"Cannot get logons today widget\n");
        !           269:        else {
        !           270:                if(shownodes)
        !           271:                        sprintf(str,"%s/%s",getnumstr(str2,nstats.ltoday),getnumstr(str3,sstats.ltoday));
        !           272:                else
        !           273:                        sprintf(str,"%s",getnumstr(str2,sstats.ltoday));
        !           274:                gtk_entry_set_text(GTK_ENTRY(w),str);
        !           275:        }
        !           276: 
        !           277:        w=glade_xml_get_widget(xml, "eTimeToday");
        !           278:        if(w==NULL)
        !           279:                fprintf(stderr,"Cannot get time today widget\n");
        !           280:        else {
        !           281:                if(shownodes)
        !           282:                        sprintf(str,"%s/%s",getnumstr(str2,nstats.ttoday),getnumstr(str3,sstats.ttoday));
        !           283:                else
        !           284:                        sprintf(str,"%s",getnumstr(str2,sstats.ttoday));
        !           285:                gtk_entry_set_text(GTK_ENTRY(w),str);
        !           286:        }
        !           287: 
        !           288:        w=glade_xml_get_widget(xml, "eEmailToday");
        !           289:        if(w==NULL)
        !           290:                fprintf(stderr,"Cannot get e-mail today widget\n");
        !           291:        else {
        !           292:                if(shownodes)
        !           293:                        sprintf(str,"%s/%s",getnumstr(str2,nstats.etoday),getnumstr(str3,sstats.etoday));
        !           294:                else
        !           295:                        sprintf(str,"%s",getnumstr(str2,sstats.etoday));
        !           296:                gtk_entry_set_text(GTK_ENTRY(w),str);
        !           297:        }
        !           298: 
        !           299:        w=glade_xml_get_widget(xml, "eFeedbackToday");
        !           300:        if(w==NULL)
        !           301:                fprintf(stderr,"Cannot get feedback today widget\n");
        !           302:        else {
        !           303:                if(shownodes)
        !           304:                        sprintf(str,"%s/%s",getnumstr(str2,nstats.ftoday),getnumstr(str3,sstats.ftoday));
        !           305:                else
        !           306:                        sprintf(str,"%s",getnumstr(str2,sstats.ftoday));
        !           307:                gtk_entry_set_text(GTK_ENTRY(w),str);
        !           308:        }
        !           309: 
        !           310:        w=glade_xml_get_widget(xml, "eNewUsersToday");
        !           311:        if(w==NULL)
        !           312:                fprintf(stderr,"Cannot get new users today widget\n");
        !           313:        else {
        !           314:                if(shownodes)
        !           315:                        sprintf(str,"%s/%s",getnumstr(str2,nstats.nusers),getnumstr(str3,sstats.nusers));
        !           316:                else
        !           317:                        sprintf(str,"%s",getnumstr(str2,sstats.nusers));
        !           318:                gtk_entry_set_text(GTK_ENTRY(w),str);
        !           319:        }
        !           320: 
        !           321:        w=glade_xml_get_widget(xml, "ePostsToday");
        !           322:        if(w==NULL)
        !           323:                fprintf(stderr,"Cannot get posts today widget\n");
        !           324:        else {
        !           325:                if(shownodes)
        !           326:                        sprintf(str,"%s/%s",getnumstr(str2,nstats.ptoday),getnumstr(str3,sstats.ptoday));
        !           327:                else
        !           328:                        sprintf(str,"%s",getnumstr(str2,sstats.ptoday));
        !           329:                gtk_entry_set_text(GTK_ENTRY(w),str);
        !           330:        }
        !           331: 
        !           332:        w=glade_xml_get_widget(xml, "eLogonsTotal");
        !           333:        if(w==NULL)
        !           334:                fprintf(stderr,"Cannot get logons total widget\n");
        !           335:        else {
        !           336:                if(shownodes)
        !           337:                        sprintf(str,"%s/%s",getnumstr(str2,nstats.logons),getnumstr(str3,sstats.logons));
        !           338:                else
        !           339:                        sprintf(str,"%s",getnumstr(str2,sstats.logons));
        !           340:                gtk_entry_set_text(GTK_ENTRY(w),str);
        !           341:        }
        !           342: 
        !           343:        w=glade_xml_get_widget(xml, "eTimeTotal");
        !           344:        if(w==NULL)
        !           345:                fprintf(stderr,"Cannot get time total widget\n");
        !           346:        else {
        !           347:                if(shownodes)
        !           348:                        sprintf(str,"%s/%s",getnumstr(str2,nstats.timeon),getnumstr(str3,sstats.timeon));
        !           349:                else
        !           350:                        sprintf(str,"%s",getnumstr(str2,sstats.timeon));
        !           351:                gtk_entry_set_text(GTK_ENTRY(w),str);
        !           352:        }
        !           353: 
        !           354:        w=glade_xml_get_widget(xml, "eEmailTotal");
        !           355:        if(w==NULL)
        !           356:                fprintf(stderr,"Cannot get email total widget\n");
        !           357:        else {
        !           358:                sprintf(str,"%s",getnumstr(str2,getmail(&cfg,0,0)));
        !           359:                gtk_entry_set_text(GTK_ENTRY(w),str);
        !           360:        }
        !           361: 
        !           362:        w=glade_xml_get_widget(xml, "eFeedbackTotal");
        !           363:        if(w==NULL)
        !           364:                fprintf(stderr,"Cannot get feedback total widget\n");
        !           365:        else {
        !           366:                sprintf(str,"%s",getnumstr(str2,getmail(&cfg,1,0)));
        !           367:                gtk_entry_set_text(GTK_ENTRY(w),str);
        !           368:        }
        !           369: 
        !           370:        w=glade_xml_get_widget(xml, "eUsersTotal");
        !           371:        if(w==NULL)
        !           372:                fprintf(stderr,"Cannot get users total widget\n");
        !           373:        else {
        !           374:                sprintf(str,"%s",getnumstr(str2,total_users(&cfg)));
        !           375:                gtk_entry_set_text(GTK_ENTRY(w),str);
        !           376:        }
        !           377: 
        !           378:        w=glade_xml_get_widget(xml, "eFilesUploadedToday");
        !           379:        if(w==NULL)
        !           380:                fprintf(stderr,"Cannot get files uploaded today widget\n");
        !           381:        else {
        !           382:                sprintf(str,"%s",getnumstr(str2,sstats.uls));
        !           383:                gtk_entry_set_text(GTK_ENTRY(w),str);
        !           384:        }
        !           385: 
        !           386:        w=glade_xml_get_widget(xml, "eBytesUploadedToday");
        !           387:        if(w==NULL)
        !           388:                fprintf(stderr,"Cannot get bytes uploaded today widget\n");
        !           389:        else {
        !           390:                sprintf(str,"%s",getsizestr(str2,sstats.ulb,TRUE));
        !           391:                gtk_entry_set_text(GTK_ENTRY(w),str);
        !           392:        }
        !           393: 
        !           394:        w=glade_xml_get_widget(xml, "eFilesDownloadedToday");
        !           395:        if(w==NULL)
        !           396:                fprintf(stderr,"Cannot get files downloaded today widget\n");
        !           397:        else {
        !           398:                sprintf(str,"%s",getnumstr(str2,sstats.dls));
        !           399:                gtk_entry_set_text(GTK_ENTRY(w),str);
        !           400:        }
        !           401: 
        !           402:        w=glade_xml_get_widget(xml, "eBytesDownloadedToday");
        !           403:        if(w==NULL)
        !           404:                fprintf(stderr,"Cannot get bytes downloaded today widget\n");
        !           405:        else {
        !           406:                sprintf(str,"%s",getsizestr(str2,sstats.dlb,TRUE));
        !           407:                gtk_entry_set_text(GTK_ENTRY(w),str);
        !           408:        }
        !           409: 
        !           410:        /* Setup the stats updater */
        !           411:        if(data != NULL)
        !           412:                g_timeout_add(1000 /* Milliseconds */, refresh_data, data);
        !           413: 
        !           414:        return(0);
        !           415: }
        !           416: 
        !           417: /* Initializes global stuff, loads first user etc */
        !           418: int read_config(void)
        !           419: {
        !           420:        char    ctrl_dir[MAX_PATH+1];
        !           421:        char    *p;
        !           422: 
        !           423:        p=getenv("SBBSCTRL");
        !           424:        if(p==NULL) {
        !           425:                display_message("Environment Error","SBBSCTRL not set","gtk-dialog-error");
        !           426:                return(-1);
        !           427:        }
        !           428:        SAFECOPY(ctrl_dir, p);
        !           429:        prep_dir("",ctrl_dir,sizeof(ctrl_dir));
        !           430:        if(!isdir(ctrl_dir)) {
        !           431:                display_message("Environment Errpr","SBBSCTRL does not point to a directory","gtk-dialog-error");
        !           432:                return(-1);
        !           433:        }
        !           434:     memset(&cfg,0,sizeof(cfg));
        !           435:     cfg.size=sizeof(cfg);
        !           436:     SAFECOPY(cfg.ctrl_dir,ctrl_dir);
        !           437: 
        !           438:        /* Read the ctrl struct */
        !           439:        refresh_events();
        !           440: 
        !           441:        /* Read the .ini file */
        !           442:        read_ini();
        !           443: 
        !           444:        /* Passing any non-NULL argument is required to set up the timeout */
        !           445:        if(refresh_data(refresh_data))
        !           446:                return(-1);
        !           447:        return(0);
        !           448: }
        !           449: 
        !           450: int main(int argc, char *argv[]) {
        !           451:     gtk_init(&argc, &argv);
        !           452:     glade_init();
        !           453: 
        !           454:     /* load the interface */
        !           455:        strcpy(glade_path, argv[0]);
        !           456:        strcpy(getfname(glade_path), "gtkmonitor.glade");
        !           457:     xml = glade_xml_new(glade_path, "MainWindow", NULL);
        !           458: 
        !           459:     /* connect the signals in the interface */
        !           460:     glade_xml_signal_autoconnect(xml);
        !           461: 
        !           462:        /* Set up the global config stuff. */
        !           463:        memset(&cfg, 0, sizeof(cfg));
        !           464:        if(read_config())
        !           465:                return(1);
        !           466: 
        !           467:     /* start the event loop */
        !           468:     gtk_main();
        !           469:     return 0;
        !           470: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.