回精華區
作者itoc.bbs@processor.tfcis.org (核心動力) 看板: plan
標題Re: 請問關於雅虎!奇摩的新聞功能
時間動力核心 (2004/02/12 Thu 12:45:28) Updated: 2006/03/17
  要先做精華區這篇
  [功能] enews-open.c 奇摩新聞轉至看板

: menu.c 適當選單加入

+ "bin/enews.so:main_enews", 0, - M_GAME,
+ "Enews       奇摩新聞",

: theme.h

#define FOOTER_VEDIT    \
COLOR1 " %s " COLOR2 " (^Z)說明 (^W)符號 (^L)重繪 (^X)檔案處理 ... \033[m"

+ #define FOOTER_ENEWS   \
+ COLOR1 " 奇摩新聞 " COLOR2 " (kj)上下篇 (↑↓←)上下離開             "
+ "                           "

  ...
  ...

#define FEETER_INNBBS   \
COLOR1 " 轉信設定 " COLOR2 " (↑/↓)上下 (PgUp/PgDn)上下頁 ... "

+ #define FEETER_ENEWS \
+ COLOR1 " 奇摩新聞 " COLOR2 " (方向)移動 (字母/數字)項目/篇數 " \
+ "(ENTER)瀏覽 (F/x) 轉寄/轉錄 (q)離開 "

: game/Makefile

SO =     ..... enews.so

: game/enews.c 新增此程式

/*-------------------------------------------------------*/
/* enews.c  ( NTHU CS MapleBBS Ver 3.10 )                */
/*-------------------------------------------------------*/
/* target : Yahoo! 奇摩新聞                              */
/* create : 02/01/27                                     */
/* update :   /  /                                       */
/* author : itoc.bbs@bbs.tnfsh.tn.edu.tw                 */
/*-------------------------------------------------------*/


#if 0

 本奇摩新聞程式需要配合 enews-open 去抓資料,crontab 如下:

# 每天 10:30AM 4:30PM 抓奇摩新聞
30 10,16 * * * bin/enews-open

 要使用 enews-open.c 必須裝有 lynx。

 文章檔案放在 run/kimo/

 資料來源:Yahoo! 奇摩新聞 http://tw.news.yahoo.com/

#endif


#include "bbs.h"


/*-------------------------------------------------------*/
/* variable                                              */
/*-------------------------------------------------------*/


/* itoc.020129: 目前不支援翻頁,所以每種分類新聞最多也是 16 條而已 */

#define MAX_ENEWS   16  /* 一頁最多有 16 項 */

static char title[MAX_ENEWS][TTLEN + 1];    /* 本分類新聞的所有標題 */
static char xname[MAX_ENEWS][10];           /* 本分類新聞的所有檔案路徑 */
static int maxitem;                         /* 本分類的共有幾篇 */

extern BCACHE *bshm;

extern void outgo_post(HDR *hdr, char *board);

#define mouts(x,y,s)    { move(x, y); outs(s); }

static void
enews_fpath(fpath, kind, fname)
  char *fpath;
  char kind;
  char *fname;
{
  sprintf(fpath, "run/kimo/%c/%s", kind, fname);
}


/*-------------------------------------------------------*/
/* E-News 選單                                           */
/*-------------------------------------------------------*/


static void
enews_item(num, cc)
  int num;
  int cc;
{
  move(6 + num, 0);
  clrtoeol();
  move(6 + num, 15);
  prints(cc == num ? "%2d " COLOR4 " %.*s \033[m" : "%2d  %.*s",
    num + 1, d_cols + 54, title[num]);  /* 太長的截掉 */
}


static void
enews_body(kind, cc)
  char kind;
  int cc;
{
  int num;

  if (!maxitem)
    return;

  for (num = 0; num < maxitem; num++)
    enews_item(num, cc);

  for (; num < MAX_ENEWS; num++)
  {
    move(6 + num, 0);
    clrtoeol();
  }

  /* 游標移去所選項的最後 */
  num = 20 + strlen(title[cc]);
  if (num > 74)     /* 太長的截掉 */
    num = 74;
  move(6 + cc, num);
}


static void
enews_neck(kind, cc)
  char kind;
  int cc;
{
  int i;
  char class[12][5] =
  {
    "政治", "社會", "國際", "兩岸", "財經", "影視",
    "體育", "生活", "休閒", "健康", "科技", "新奇"
  };

  move(4, 0);
  clrtoeol();
  move(4, 4);
  for (i = 'A'; i <= 'L'; i++)
    prints(i == kind ? "\033[1;36m%c\033[37;41m%s\033[m " :
      "\033[1;36m%c\033[m%s ", i, class[i - 'A']);

  enews_body(kind, cc);
}


static void
enews_head(kind, cc)
  char kind;
  int cc;
{
  clear();

  mouts(0, 8, "\033[1;37;42m  ╔═╮╗ ═══════════════"
    "═════════╮  \033[m");
  mouts(1, 8, "\033[1;37;42m  ║  ║║╭═╮╭  ╮╭═╮     \033[33m"
    "雅虎!奇摩新聞\033[37m            ║  \033[m");
  mouts(2, 8, "\033[1;37;42m  ║  ║║╠═╝║║║╰═╮     \033[33m"
    "http://tw.news.yahoo.com/\033[37m ║  \033[m");
  mouts(3, 8, "\033[1;37;42m  ╚═╰╩╩═╩╩╩╩══╯ ══════"
    "═════════╯  \033[m");

  outf(FEETER_ENEWS);

  enews_neck(kind, cc);
}


static void
enews_load(kind)
  char kind;
{
  char fpath[64];
  FILE *fp;
  ENEWS enews;

  maxitem = 0;

  enews_fpath(fpath, kind, ".ENEWS");
  if (!(fp = fopen(fpath, "r")))
    return;

  while (fread(&enews, sizeof(ENEWS), 1, fp) == 1 && maxitem < MAX_ENEWS)
  {
    strcpy(title[maxitem], enews.title);
    strcpy(xname[maxitem], enews.xname);
    maxitem++;
  }
  fclose(fp);
}


/*-------------------------------------------------------*/
/* 其他功能                                              */
/*-------------------------------------------------------*/


static int      /* 回傳最後讀到哪一篇 */
enews_browse(kind, cc)
  char kind;
  int cc;
{
  int key;
  char fpath[64];

  for (;;)
  {
    if (cc >= maxitem)
      break;

    enews_fpath(fpath, kind, xname[cc]);

    /* Thor.990204: 為考慮more 傳回值 */
    if ((key = more(fpath, FOOTER_ENEWS)) < 0)
      break;

    if (!key)       /* 已讀完 */
      key = vkey();

    switch (key)
    {
    case KEY_RIGHT:
    case KEY_PGDN:
    case KEY_DOWN:
    case ' ':
    case 'j':
      if (cc < maxitem - 1)
      {
        cc++;
        continue;
      }
      break;

    case KEY_UP:
    case KEY_PGUP:
    case 'k':
      if (cc > 0)
      {
        cc--;
        continue;
      }
      break;
    }

    break;
  }

  return cc;
}


static void
enews_cross(kind, cc)       /* 提供單篇轉錄到看板 */
  char kind;
  int cc;
{
  int rc, battr, xbno;
  char xboard[IDLEN + 1], xfolder[64], fpath[64];
  HDR xpost;

  if (!cuser.userlevel)
    return;

  if (ask_board(xboard, BRD_W_BIT, "\n\n\033[1;33m請挑選適當的看板,"
    "切勿轉錄超過三板。\033[m\n\n"))
  {
    rc = vget(2, 0, "(S)存檔 (L)站內 (Q)取消?[Q] ", fpath, 3, LCECHO);
    if (rc == 'l' || rc == 's')
    {
      enews_fpath(fpath, kind, xname[cc]);
      brd_fpath(xfolder, xboard, fn_dir);

      /* 轉錄新聞就直接原文轉載,但是作者換為自己 */
      hdr_stamp(xfolder, HDR_COPY | 'A', &xpost, fpath);
      strcpy(xpost.owner, cuser.userid);
      strcpy(xpost.nick, cuser.username);
      strcpy(xpost.title, title[cc]);

      xbno = brd_bno(xboard);
      battr = (bshm->bcache + xbno)->battr;

      /* Thor.990111: 在可以轉出前, 要check user有沒有轉出的權力? */
      if (!HAS_PERM(PERM_INTERNET) || (battr & BRD_NOTRAN))
        rc = 'l';

      if (rc == 's' && (!(battr & BRD_NOTRAN)))
        xpost.xmode = POST_OUTGO;

      rec_bot(xfolder, &xpost, sizeof(HDR));

      if (rc == 's' && (!(battr & BRD_NOTRAN)))
        outgo_post(&xpost, xboard);

      btime_update(xbno);

      /* Thor.981205: check 被轉的板有沒有列入紀錄? */
      if (battr & BRD_NOCOUNT)
      {
        vmsg("轉錄完成,文章不列入紀錄,敬請包涵。");
      }
      else
      {
        cuser.numposts++;
        vmsg("轉錄完成");
      }
    }
  }
  enews_head(kind, cc);
}


static int
enews_forward(kind, cc)     /* 提供單篇轉寄 */
  char kind;
  int cc;
{
  char rcpt[64];
  char fpath[64], folder[64], *userid;
  int userno, rc;
  int method;       /* 轉寄到 0:站外 >0:自己 <0:其他站內使用者 */

  if (!HAS_PERM(PERM_INTERNET) || HAS_STATUS(STATUS_MAILOVER))
    return XO_NONE;

  strcpy(rcpt, cuser.email);
  if (!vget(b_lines, 0, "目的地:", rcpt, sizeof(rcpt), GCARRY))
    return XO_FOOT;

  userid = cuser.userid;
  userno = 0;

  if (!mail_external(rcpt)) /* 中途攔截 */
  {
    if (!str_cmp(rcpt, userid))
    {
      /* userno = cuser.userno; */  /* Thor.981027: 寄精選集給自己不通知自己 */
      method = 1;
    }
    else
    {
      if ((userno = acct_userno(rcpt)) <= 0)
      {
        zmsg(err_uid);
        return XO_FOOT;
      }
      method = -1;
    }

    usr_fpath(folder, rcpt, fn_dir);
  }
  else
  {
    if (not_addr(rcpt))
    {
      zmsg(err_email);
      return XO_FOOT;
    }

    method = 0;
  }

  enews_fpath(fpath, kind, xname[cc]);

  if (method)           /* 轉寄站內 */
  {
    HDR mhdr;

    hdr_stamp(folder, HDR_COPY, &mhdr, fpath);

    if (method > 0)     /* 轉寄自己 */
    {
      strcpy(mhdr.owner, "[精 選 集]");
      mhdr.xmode = MAIL_READ | MAIL_NOREPLY;
    }
    else            /* 轉寄其他使用者 */
    {
      strcpy(mhdr.owner, userid);
    }
    strcpy(mhdr.nick, cuser.username);
    strcpy(mhdr.title, title[cc]);
    rc = rec_add(folder, &mhdr, sizeof(HDR));
  }
  else              /* 轉寄站外 */
  {
    rc = bsmtp(fpath, title[cc], rcpt, 0);
  }

  if (userno > 0 && rc >= 0)
    m_biff(userno);

  zmsg(rc < 0 ? "部份信件無法寄達" : "寄信完畢");

  enews_head(kind, cc);
  return XO_NONE;
}


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


int
main_enews()
{
  int cc, ch;
  char kind;

  kind = 'A';   /* 分類 */
  cc = 0;       /* 第幾篇 */

  enews_load(kind);
  enews_head(kind, cc);

  while (ch = vkey())
  {
    if (ch >= 'a' && ch <= 'l')
    {
      kind = ch - 32;       /* 變大寫 */
      cc = 0;
      enews_load(kind);
      enews_neck(kind, cc);
      continue;
    }

    if (ch >= '1' && ch <= '9')
    {
      char ans[5];

      ans[0] = ch;
      ans[1] = '\0';
      vget(b_lines, 0, "跳至第幾項:", ans, 4, GCARRY);
      outf(FEETER_ENEWS);   /* 重繪 feet */

      ch = atoi(ans);
      if (ch > 0  && ch <= maxitem)
      {
    enews_item(cc, 12345);  /* 重繪原來那行 */
    cc = ch - 1;
    enews_item(cc, cc);
      }
      continue;
    }

    switch (ch)
    {
    case 'q':
    case 'e':
      return 0;

    case KEY_RIGHT:
      kind = kind < 'L' ? kind + 1 : 'A';
      cc = 0;
      enews_load(kind);
      enews_neck(kind, cc);
      break;

    case KEY_LEFT:
      kind = kind > 'A' ? kind - 1 : 'L';
      cc = 0;
      enews_load(kind);
      enews_neck(kind, cc);
      break;

    case KEY_DOWN:
      enews_item(cc, 12345);     /* 重繪原來那行 */
      cc = cc < maxitem - 1 ? cc + 1 : 0;
      enews_item(cc, cc);
      break;

    case KEY_UP:
      enews_item(cc, 12345);    /* 重繪原來那行 */
      cc = cc > 0 ? cc - 1 : maxitem - 1;
      enews_item(cc, cc);
      break;

    case '\n':
      cc = enews_browse(kind, cc);
      enews_head(kind, cc);
      break;

    case '0':
    case KEY_HOME:
      if (cc != 0)
      {
        enews_item(cc, 12345);  /* 重繪原來那行 */
        cc = 0;
        enews_item(cc, cc);
      }
      break;

    case KEY_END:
      if (cc != maxitem - 1)
      {
        enews_item(cc, 12345);  /* 重繪原來那行 */
        cc = maxitem - 1;
        enews_item(cc, cc);
      }
      break;

    case 'x':
      enews_cross(kind, cc);
      break;

    case 'F':
      if (enews_forward(kind, cc) == XO_FOOT)
        outf(FEETER_ENEWS);
      break;
    }
  }
}

--
  Origin:  Maple-itoc˙動力核心  processor.tfcis.org 
  Author: itoc pc512-2.ee.nctu.edu.tw 發表
精華選讀←離開[主題上]主題下(k)上篇(j)下篇S/a搜尋 G串列 TAB精華 ↑↓捲 Pg/Space翻