回精華區
作者itoc (站上人數:802), 信區: plan
標題[功能] 刪除過久沒有新文章的看板
時間2005/04/05 Tue 16:13:03 Updated: 2005/12/28
※ 引述《drewlin.bbs@bbs.seehere.org (eternity.)》之銘言:
> 希望系統能夠自動刪除三個月以上沒有新文章的看板

: global.h

#define FN_RUN_PAL      "run/pal.log"   /* 朋友超過上限記錄 */
+ #define FN_RUN_EXPIREBRD "run/expirebrd" /* 系統砍除看板記錄 */

: battr.h

+ #define BRD_NOEXPIRE  0x80    /* 不會被系統砍除 */

- #define NUMBATTRS   7
+ #define NUMBATTRS   8

- #define STR_BATTR   "zTcsvA%"
+ #define STR_BATTR   "zTcsvA%e"

   "不評分看板",         /* BRD_NOSCORE */
+  "不被系統砍除看板",   /* BRD_NOEXPIRE */

: account.c:main()

    sprintf(title, "%s寄信記錄", date);
    keeplog(FN_RUN_MAIL_LOG, BN_SECURITY, title, 2);

+   sprintf(title, "%s系統砍除看板記錄", date);
+   keeplog(FN_RUN_EXPIREBRD, BN_SECURITY, title, 2);


: crontab -e 加入

4 4 4 * * bin/expireboard > /dev/null 2>&1

: src/util/Makefile 加入 expireboard

EXE =   ... expireboard

: src/util/expireboard.c 新增程式如下

/*-------------------------------------------------------*/
/* util/expireboard.c   ( NTHU CS MapleBBS Ver 3.10 )    */
/*-------------------------------------------------------*/
/* target : 砍除過久沒有新文章的看板                     */
/* create : 05/04/05                                     */
/* update :   /  /                                       */
/* author : itoc.bbs@bbs.tnfsh.tn.edu.tw                 */
/*-------------------------------------------------------*/


#include "bbs.h"

#define THRESHOLD_TIME      (40 * 86400) /* 砍除超過 40 天沒文章的看板 */
#define THRESHOLD_NOTE_TIME (30 * 86400) /* 砍板前 30 天通知板主 */
// crontab 裡 expireboard 的執行週期要跟 THRESHOLD_NOTE_TIME 同步 


/*-------------------------------------------------------*/
/* 通知信                                                */
/*-------------------------------------------------------*/


static void
mail_to_him(userid, brdname)
  char *userid, *brdname;
{
  HDR hdr;
  char folder[64];

  usr_fpath(folder, userid, NULL);
  if (!dashd(folder))    /* 避免該 ID 不存在 */
    return;

  usr_fpath(folder, userid, FN_DIR);
  hdr_stamp(folder, HDR_LINK, &hdr, "etc/expirebrd_note");
  strcpy(hdr.owner, STR_SYSOP);
  strcpy(hdr.nickname, SYSOPNICK);
  sprintf(hdr.title, "[%s] 板即將被砍除", brdname);
  rec_add(folder, &hdr, sizeof(HDR));
}


static void
note_expire(brd)    /* 找出板主 */
  BRD *brd;
{
  char *ptr, *str, buf[BMLEN + 1];
  int len, alllen;

  sprintf(buf, "%s", brd->BM);
  alllen = 0;
  ptr = str = buf;

  for (; ptr = strchr(str, '/') ;)
  {
    *ptr = '\0';
    mail_to_him(str, brd->brdname);
    len = strlen(str);
    alllen += (len + 1);    /* 板主ID + '/' */
    str = buf + alllen;
  }
  mail_to_him(str, brd->brdname);         /* 最後一筆資料另外處理 */
}


/*-------------------------------------------------------*/
/* 主程式                                                */
/*-------------------------------------------------------*/


static time_t now;
static time_t delta;      /* 最後一篇文章距目前幾秒 */
static int page;          /* 有幾篇文章 */


static void
expire(brd)
  BRD *brd;
{
  int fd, fsize;
  char folder[64];
  HDR hdr;
  struct stat st;

  brd_fpath(folder, brd->brdname, FN_DIR);

  if ((fd = open(folder, O_RDONLY)) >= 0 && !fstat(fd, &st))
  {
    fsize = st.st_size;
    page = fsize / sizeof(HDR);

    if (page <= 0)  /* 沒有文章則看開板時間 */
    {
      delta = brd->bstamp;
    }
    else
    {
      lseek(fd, fsize - sizeof(HDR), SEEK_SET);
      read(fd, &hdr, sizeof(HDR));
      delta = hdr.chrono;
    }
    delta = now - delta;
    close(fd);
  }
}


static BCACHE *bshm;


static void
init_bshm()
{
  /* itoc.030727: 在開啟 bbsd 之前,應該就要執行過 account,
     所以 bshm 應該已設定好 */

  bshm = shm_new(BRDSHM_KEY, sizeof(BCACHE));

  if (bshm->uptime <= 0)        /* bshm 未設定完成 */
    exit(0);
}


int
main()
{
  int pos;
  BRD brd, *bhdr;
  char fpath[64];
  FILE *fp;

  chdir(BBSHOME);

  if (!(fp = fopen(FN_RUN_EXPIREBRD, "w")))
    return -1;

  time(&now);
  init_bshm();

  fprintf(fp, "下列看板已於 %s 被系統砍除:\n\n", Btime(&now));

  pos = 0;
  while (!rec_get(FN_BRD, &brd, sizeof(BRD), pos))
  {
    if (*brd.brdname && !(brd.battr & BRD_NOEXPIRE))
    {
      expire(&brd);

      if (delta >= THRESHOLD_TIME)
      {
        gem_fpath(fpath, brd.brdname, NULL);
        f_rm(fpath);
        f_rm(fpath + 4);

        memset(&brd, 0, sizeof(BRD));
        sprintf(brd.title, "[%s] deleted by <crontab>", brd.brdname);
        rec_put(FN_BRD, &brd, sizeof(BRD), pos, NULL);

        bhdr = bshm->bcache + pos;
        memcpy(bhdr, &brd, sizeof(BRD));

        fprintf(fp, "  %s\n", brd.brdname);
      }
      else if (delta >= THRESHOLD_NOTE_TIME)
      {
        note_expire(&brd);
      }
    }
    pos++;
  }

  fclose(fp);

  return 0;
}

: etc/expirebrd_note 新增此檔案,內容如下

作者: SYSOP (站長) 站內: [系統公告]
標題: 砍板通知
時間: 就是現在

 您好:

     由於此板使用率過低,所以此板即將被系統自動砍除,若您不希望看板
 被砍除,請定期於看板上發表文章。

--
                                          站務管理員 SYSOP



--
□ 本文章由 itocthree.Dorm11.NCTU.edu.tw 發表
精華選讀←離開[主題上]主題下(k)上篇(j)下篇S/a搜尋 G串列 TAB精華 ↑↓捲 Pg/Space翻