summaryrefslogblamecommitdiffstats
path: root/mbbsd/angel.c
blob: 2e9182198e589dea81b2c6ed0d88638763025fe5 (plain) (tree)





















                                              
                                















































































































                                                                             
                  


                   
                                                                                        
                            
                 
                                             


                                                                                              
                         
         






                                                       


                                                                                              
                         
         
 







                                                                             






























































































































































                                                                                                           
/* $Id$ */
#include "bbs.h"

// PTT-BBS Angel System

#ifdef PLAY_ANGEL

void 
angel_toggle_pause()
{
    if (!HasUserPerm(PERM_ANGEL) || !currutmp)
    return;
    currutmp->angelpause ++;
    currutmp->angelpause %= ANGELPAUSE_MODES;

    // maintain deprecated value
    cuser.uflag2 &= ~UF2_ANGEL_OLDMASK;
}

void 
angel_load_data()
{
    // TODO cache angelmsg here.
}

int
t_changeangel(){
    char buf[4];

    /* cuser.myangel == "-" means banned for calling angel */
    if (cuser.myangel[0] == '-' || cuser.myangel[1] == 0) return 0;

    getdata(b_lines - 1, 0,
        "更換小天使後就無法換回了喔! 是否要更換小天使? [y/N]",
        buf, 3, LCECHO);
    if (buf[0] == 'y' || buf[0] == 'Y') {
    char buf[100];
    snprintf(buf, sizeof(buf), "%s小主人 %s 換掉 %s 小天使\n",
        ctime4(&now), cuser.userid, cuser.myangel);
    buf[24] = ' '; // replace '\n'
    log_file(BBSHOME "/log/changeangel.log", LOG_CREAT, buf);

    cuser.myangel[0] = 0;
    outs("小天使更新完成,下次呼叫時會選出新的小天使");
    }
    return XEASY;
}

int 
t_angelmsg(){
    char msg[3][74] = { "", "", "" };
    char nick[10] = "";
    char buf[512];
    int i;
    FILE* fp;

    setuserfile(buf, "angelmsg");
    fp = fopen(buf, "r");
    if (fp) {
    i = 0;
    if (fgets(msg[0], sizeof(msg[0]), fp)) {
        chomp(msg[0]);
        if (strncmp(msg[0], "%%[", 3) == 0) {
        strlcpy(nick, msg[0] + 3, 7);
        move(4, 0);
        prints("原有暱稱:%s小天使", nick);
        msg[0][0] = 0;
        } else
        i = 1;
    } else
        msg[0][0] = 0;

    move(5, 0);
    outs("原有留言:\n");
    if(msg[0][0])
        outs(msg[0]);
    for (; i < 3; ++i) {
        if(fgets(msg[i], sizeof(msg[0]), fp)) {
        outs(msg[i]);
        chomp(msg[i]);
        } else
        break;
    }
    fclose(fp);
    }

    getdata_buf(11, 0, "小天使暱稱:", nick, 7, 1);
    do {
    move(12, 0);
    clrtobot();
    outs("不在的時候要跟小主人說什麼呢?"
         "最多三行,按[Enter]結束");
    for (i = 0; i < 3 &&
        getdata_buf(14 + i, 0, ":", msg[i], sizeof(msg[i]), DOECHO);
        ++i);
    getdata(b_lines - 2, 0, "(S)儲存 (E)重新來過 (Q)取消?[S]",
        buf, 4, LCECHO);
    } while (buf[0] == 'E' || buf[0] == 'e');
    if (buf[0] == 'Q' || buf[0] == 'q')
    return 0;
    setuserfile(buf, "angelmsg");
    if (msg[0][0] == 0)
    unlink(buf);
    else {
    FILE* fp = fopen(buf, "w");
    if(nick[0])
        fprintf(fp, "%%%%[%s\n", nick);
    for (i = 0; i < 3 && msg[i][0]; ++i) {
        fputs(msg[i], fp);
        fputc('\n', fp);
    }
    fclose(fp);
    }
    return 0;
}

inline int
angel_reject_me(userinfo_t * uin){
    int* iter = uin->reject;
    int unum;
    while ((unum = *iter++)) {
    if (unum == currutmp->uid) {
        return 1;
    }
    }
    return 0;
}


static int
FindAngel(void){
    int nAngel;
    int i, j;
    int choose;
    int trial = 0;
    userinfo_t *u;

    do{
    nAngel = 0;
    // since we have many, many angels now, let's ignore angels in angelpause state.
    j = SHM->currsorted;
    u = NULL;
    for (i = 0; i < SHM->UTMPnumber; ++i)
    {
        u = &SHM->uinfo[SHM->sorted[j][0][i]];
        if ((u->userlevel & PERM_ANGEL) && (!u->angelpause) && (u->mode != DEBUGSLEEPING))
        ++nAngel;
    }

    if (nAngel == 0)
        return 0;

    choose = random() % nAngel + 1;
    j = SHM->currsorted;
    for (i = 0; i < SHM->UTMPnumber && choose; ++i)
    {
        u = &SHM->uinfo[SHM->sorted[j][0][i]];
        if ((u->userlevel & PERM_ANGEL) && (!u->angelpause) && (u->mode != DEBUGSLEEPING))
        --choose;
    }

    // u should be correct now! No need to check angelpause in this time.
    // u = &(SHM->uinfo[SHM->sorted[j][0][i-1]]);
    if (choose == 0 && u &&
        (u->uid != currutmp->uid) &&
        (u->userlevel & PERM_ANGEL) &&
        !angel_reject_me(u) &&
        u->userid[0]){
        strlcpy(cuser.myangel, u->userid, sizeof(cuser.myangel));
        passwd_update(usernum, &cuser);
        return 1;
    }
    }while(++trial < 5);
    return 0;
}

static inline void
GotoNewHand(){
    char old_board[IDLEN + 1] = "";
    int canRead = 1;

    if (currutmp && currutmp->mode == EDITING)
    return;

    // usually crashed as 'assert(currbid == brc_currbid)'
    if (currboard[0]) {
    strlcpy(old_board, currboard, IDLEN + 1);
    currboard = "";// force enter_board
    }

    if (enter_board(BN_NEWBIE) == 0)
    canRead = 1;

    if (canRead)
    Read();

    if (canRead && old_board[0])
    enter_board(old_board);
}


static inline void
NoAngelFound(const char* msg){
    move(b_lines, 0);
    outs(msg);
    if (currutmp == NULL || currutmp->mode != EDITING)
    outs(",請先在新手板上尋找答案或按 Ctrl-P 發問");
    clrtoeol();
    refresh();
    sleep(1);
    GotoNewHand();
    return;
}

static inline void
AngelNotOnline(){
    char buf[PATHLEN] = "";
    const static char* const not_online_message = "您的小天使現在不在線上";

    // TODO cache angel's nick name!

    if (cuser.myangel[0] != '-')
    sethomefile(buf, cuser.myangel, "angelmsg");
    if (cuser.myangel[0] == '-' || !dashf(buf))
    NoAngelFound(not_online_message);
    else {
    time4_t mod = dasht(buf);
    FILE* fp = fopen(buf, "r");
    clear();
    showtitle("小天使留言", BBSNAME);
    move(4, 0);
    buf[0] = 0;
    fgets(buf, sizeof(buf), fp);
    if (strncmp(buf, "%%[", 3) == 0) {
        chomp(buf);
        prints("您的%s小天使現在不在線上", buf + 3);
        fgets(buf, sizeof(buf), fp);
    } else
        outs(not_online_message);

    outs("\n祂留言給你:\n");
    outs(ANSI_COLOR(1;31;44) "⊙┬──────────────┤" ANSI_COLOR(37) ""
         "小天使留言" ANSI_COLOR(31) "├──────────────┬⊙" ANSI_RESET "\n");
    outs(ANSI_COLOR(1;31) "╭┤" ANSI_COLOR(32) " 小天使                          "
         "                                     " ANSI_COLOR(31) "├╮" ANSI_RESET "\n");
    do {
        chomp(buf);
        prints(ANSI_COLOR(1;31) "│" ANSI_RESET "%-74.74s" ANSI_COLOR(1;31) "│" ANSI_RESET "\n", buf);
    } while (fgets(buf, sizeof(buf), fp));

    outs(ANSI_COLOR(1;31) "╰┬──────────────────────"
        "─────────────┬╯" ANSI_RESET "\n");
    outs(ANSI_COLOR(1;31;44) "⊙┴─────────────────────"
        "──────────────┴⊙" ANSI_RESET "\n");
    prints("%55s%s", "留言日期: ", Cdatelite(&mod));


    move(b_lines - 4, 0);
    outs("小主人使用上問題找不到小天使請到新手版(" BN_NEWBIE ")\n"
         "              想留言給小天使請到許\願版(AngelPray)\n"
         "                  想找看板在哪的話可到(AskBoard)\n"
         "請先在各板上尋找答案或按 Ctrl-P 發問");
    pressanykey();

    GotoNewHand();
    }
}

static void
TalkToAngel(){
    static int AngelPermChecked = 0;
    userinfo_t* uent;
    userec_t xuser;

    if (strcmp(cuser.myangel, "-") == 0){
    AngelNotOnline();
    return;
    }

    if (cuser.myangel[0] && !AngelPermChecked) {
    getuser(cuser.myangel, &xuser); // XXX if user doesn't exist
    if (!(xuser.userlevel & PERM_ANGEL))
        cuser.myangel[0] = 0;
    }
    AngelPermChecked = 1;

    if (cuser.myangel[0] == 0 && ! FindAngel()){
    NoAngelFound("現在沒有小天使在線上");
    return;
    }

    uent = search_ulist_userid(cuser.myangel);
    if (uent == 0 || uent->angelpause || angel_reject_me(uent)){
    AngelNotOnline();
    return;
    }

    more("etc/angel_usage", NA);

    /* 這段話或許可以在小天使回答問題時 show 出來
    move(b_lines - 1, 0);
    outs("現在你的id受到保密,回答你問題的小天使並不知道你是誰       \n"
         "你可以選擇不向對方透露自己身份來保護自己                   ");
     */

    my_write(uent->pid, "問小天使: ", "小天使", WATERBALL_ANGEL, uent);
    return;
}

void
CallAngel(){
    static int      entered = 0;
    screen_backup_t old_screen;

    if (!HasUserPerm(PERM_LOGINOK) || entered)
    return;
    entered = 1;

    scr_dump(&old_screen);

    TalkToAngel();

    scr_restore(&old_screen);

    entered = 0;
}

#endif // PLAY_ANGEL