Newer
Older
tuved / channel.c
@reddawg reddawg on 15 Nov 2007 16 KB sync
/*
  (c) 2007 Christopher Olsen
  $Id$
*/

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <assert.h>

#include "tuved.h"

tuveChanList_t *channels = 0x0;

tuveChanList_t *addChan(const char *channel);

int tuveChanList(myConnections_t *userConnection) {
  char data[1024];
  tuveChanList_t *tmpChan = 0x0;

  sprintf(data,"LIST:Channel:users:Topic\n");
  sSendData(userConnection,data);

  for (tmpChan = channels;tmpChan != 0x0;tmpChan = tmpChan->next) {
    sprintf(data,"LIST:%s:%i:%s:%s\n",tmpChan->channel,tmpChan->userCount,tmpChan->topic,tmpChan->videoTitle);
    sSendData(userConnection,data);
    }
  return(0x0);
  }

int tuveChanPart(const char *channel,myConnections_t *userConnection) {
  char output[512];
  short inChan = 0x0;
  
  if (tuveRemoveFromChanList(channel,userConnection) == 0x1) {
    writeLog(0,"ERROR: Can not remove %s from %s\n",userConnection->userInfo.username,channel);
    inChan = 1;
    } 
  if (tuveDelChan(channel,userConnection) == 0x1) {
    writeLog(0,"ERROR: Can not remove %s from %s's List\n",channel,userConnection->userInfo.username);
    inChan = 1;
    }
    
  if (inChan == 0x0) {
    sprintf(output,"MSG:TUveD:%s:%s Part (Left Channel)\n",channel,userConnection->userInfo.username);
    tuveSendAllInChan(channel,0x0,output);
    sprintf(output,"PART:%s:%s\n",channel,userConnection->userInfo.username);
    tuveSendAllInChan(channel,0x0,output);
    return(0x0);
    }
    
  return(0x1);
  } /* End tuveChanPart(); */
  
/*
 * Joins A User To A Channel
 */
int 
tuveChanJoin(const char *channel,myConnections_t *userConnection) {
  char output[256];
  tuveChanList_t *tmpChan = 0x0;
  int min, sec;
  int i = 0x0;

  tmpChan = findChan(channel);

  if (tmpChan != 0x0) {
    for (i = 0x0;i < MAX_BANS;i++) {
      if (tmpChan->bans[i] == userConnection->userInfo.uid) {
        sprintf(output,"MSG:TUveD:%s:You are banned from %s\n",channel,channel);
        sSendData(userConnection,output);
        return(0x1);    
        }
      } 
    }

  if (tuveAddChan(channel,userConnection) != 0x0) return(0x1);

  /* Send JOIN to all users in the channel */
  sprintf(output,"JOIN:%s:%s\n",channel,userConnection->userInfo.username);
  tuveSendAllInChan(channel,userConnection,output);

  tmpChan = findChan(channel);
  assert(tmpChan);

  sprintf(output,"CURPOS:%i:%s:%s:%i:%i\n",tmpChan->songTime - (tmpChan->videoEnd - (time(NULL) + VIDE_PAD_TIME)),tmpChan->videoFile,tmpChan->videoTitle,tmpChan->songTime,tmpChan->vid);
  sSendData(userConnection,output);

  min = tmpChan->songTime / 60;
  sec = tmpChan->songTime % 60;

  sprintf(output,"MSG:TUveD:%s:Playing %s (%i:%.2i)\n",channel,tmpChan->videoChanTitle,min,sec);
  sSendData(userConnection,output);
    
  /* Notify people in the channel that someone has joined */
  sprintf(output,"MSG:TUveD:%s:%s (%s) has joined the channel.\n",channel,userConnection->userInfo.username,userConnection->host);
  tuveSendAllInChan(channel,userConnection,output);

  return(0x0);
  }

int tuveDelUserChans(myConnections_t *userConnection,char *msg) {
  char output[256];
  tuveUserChans_t *tmpChan  = 0x0;
  tuveUserChans_t *tmpChan2 = 0x0;

  tmpChan = userConnection->userInfo.chans;
  tmpChan2 = tmpChan;

  for (;tmpChan != 0x0;tmpChan = tmpChan->next) {
    sprintf(output,"MSG:TUveD:%s:%s Quit (%s)\n",tmpChan->channel,userConnection->userInfo.username,msg);
    tuveSendAllInChan(tmpChan->channel,userConnection,output);
    sprintf(output,"PART:%s:%s\n",tmpChan->channel,userConnection->userInfo.username);
    tuveSendAllInChan(tmpChan->channel,userConnection,output);
    tuveRemoveFromChanList(tmpChan->channel,userConnection);
    free(tmpChan2);
    tmpChan2 = tmpChan->next;
    }

  if (tmpChan2 != 0x0) {
    free(tmpChan2);
    }

  return(0x0);
  }

int tuveAddChan(const char *channel,myConnections_t *userConnection) {
  tuveUserChans_t *tmpChan = 0x0;

  if (userConnection->userInfo.chans == 0x0) {
    userConnection->userInfo.chans = (tuveUserChans_t *)calloc(1,sizeof(tuveUserChans_t));
    userConnection->userInfo.chans->prev = 0x0;
    userConnection->userInfo.chans->next = 0x0;
    sprintf(userConnection->userInfo.chans->channel,channel);
    }
  else {
    tmpChan = (tuveUserChans_t *)calloc(1,sizeof(tuveUserChans_t));   
    tmpChan->prev = 0x0;
    sprintf(tmpChan->channel,channel);
    tmpChan->next = userConnection->userInfo.chans;
    userConnection->userInfo.chans->prev = tmpChan;
    userConnection->userInfo.chans = tmpChan;
    }

  tuveAddToChanList(channel,userConnection);

  return(0x0);
  }
  
int tuveDelChan(const char *channel,myConnections_t *userConnection) {
  tuveUserChans_t *tmpChan = 0x0;

  if (channel == 0x0)
    return(0x1);

  for (tmpChan = userConnection->userInfo.chans;tmpChan != 0x0;tmpChan = tmpChan->next) {
    if (!strcasecmp(tmpChan->channel,channel)) {
      writeLog(2,"Found %s On %s And Removed\n",tmpChan->channel,userConnection->userInfo.username);
      if (tmpChan->prev != 0x0)
        tmpChan->prev->next = tmpChan->next;
      else
        userConnection->userInfo.chans = tmpChan->next;
      if (tmpChan->next != 0x0)
        tmpChan->next->prev = tmpChan->prev;
      free(tmpChan);
      return(0x0);
      }
    }
  return(0x1);
  }

int tuveRemoveFromChanList(const char *channel,myConnections_t *userConnection) {
  tuveChanList_t *tmpChannel = 0x0;
  tuveUserList_t *tmpUsers   = 0x0;

  tmpChannel = findChan(channel);

  if (tmpChannel == 0x0) {
    writeLog(1,"tuveRemoveFromChanList: findChan failed!\n");
    return(0x1);
    }
   
  tmpUsers = tmpChannel->users;

  writeLog(2,"Freeing User From Chan: %s\n",channel);
  
  pthread_mutex_lock(&chanMutex);

  for (;tmpUsers != 0x0;tmpUsers = tmpUsers->next) {
    if (!strcasecmp(tmpUsers->user->userInfo.username,userConnection->userInfo.username)) {
      writeLog(3,"Found and removed user: %s\n",tmpUsers->user->userInfo.username);

      if (tmpUsers->prev != 0x0)
        tmpUsers->prev->next = tmpUsers->next;
      else 
         tmpChannel->users = tmpUsers->next;

      if (tmpUsers->next != 0x0)
        tmpUsers->next->prev = tmpUsers->prev;

      if (tmpChannel->nextUser == tmpUsers) {
        if (tmpUsers->next != 0x0)
          tmpChannel->nextUser = tmpUsers->next;
        else if (tmpChannel->users != 0x0)
          tmpChannel->nextUser = tmpChannel->users;
        else 
          tmpChannel->nextUser = 0x0;
        }
      tmpChannel->count = 0x0;

      tmpChannel->userCount--;

      free(tmpUsers);
      writeLog(3,"User Freed\n");
      pthread_mutex_unlock(&chanMutex);
      return(0x0);
      }
    }
  
  pthread_mutex_unlock(&chanMutex);
  return(0x1);
  }

int 
tuveAddToChanList(const char *channel,myConnections_t *userConnection) {
  tuveChanList_t *tmpChannel = 0x0;
  tuveUserList_t *tmpUsers   = 0x0;

  int deltaTime, day, hour, min, sec;
  char output[1024];
  //mji char topicTime[1024];
 
  tmpChannel = findChan(channel);

  // tmpChannel is okay to be null here  

  if (tmpChannel == 0x0) {
    writeLog(2,"Channel %s does not exist adding to list\n",channel);
    tmpChannel = addChan(channel);
    } 

  for (tmpUsers = tmpChannel->users;tmpUsers != 0x0;tmpUsers = tmpUsers->next) {
    if (!strcasecmp(tmpUsers->user->userInfo.username,userConnection->userInfo.username)) {
      writeLog(2,"User: %s already in channel %s\n",userConnection->userInfo.username,channel);
      return(0x0);
      }
    }

  tmpUsers = (tuveUserList_t *)calloc(1,sizeof(tuveUserList_t));

  tmpUsers->user = userConnection;
  tmpUsers->prev = 0x0;
  
  pthread_mutex_lock(&chanMutex);

  if (tmpChannel->users == 0x0) {
    tmpUsers->next = 0x0;
    tmpChannel->users = tmpUsers;
    }
  else {
    tmpUsers->next = tmpChannel->users;
    tmpChannel->users->prev = tmpUsers;
    tmpChannel->users = tmpUsers;
    }

  if (tmpChannel->nextUser == 0x0) {
    tmpChannel->nextUser = tmpUsers;
    tmpChannel->count = 0x0;
    }

  tmpChannel->userCount++;

  memset(output,0x0,256);
  //sprintf(output,"JOIN:%s:@TUveBOT",tmpChannel->channel);

  /* Send the new user the channel list */
  for (tmpUsers = tmpChannel->users;tmpUsers != 0x0;tmpUsers = tmpUsers->next) {
    if (strlen(output) > 0)
      sprintf(output,"%s:%s",output,tmpUsers->user->userInfo.username);
    else
      sprintf(output,"JOIN:%s:%s",tmpChannel->channel,tmpUsers->user->userInfo.username);
    }

  if (strlen(output) > 0) {
    sprintf(output,"%s\n",output);
    sSendData(userConnection,output);
    }

  sprintf(output,"TOPIC:%s:%s\n",tmpChannel->channel,tmpChannel->topic);
  sSendData(userConnection,output);
  sprintf(output,"MSG:TUveD:%s:Topic for %s: %s\n",tmpChannel->channel,tmpChannel->channel,tmpChannel->topic);
  sSendData(userConnection,output);
  deltaTime = time(NULL) - tmpChannel->topicSet;
  day = deltaTime / 86400;
  deltaTime -= (86400 * day);
  hour = deltaTime / 3600;
  deltaTime -= (3600 * hour);
  min = deltaTime / 60;
  deltaTime -= (60 * min);
  sec = deltaTime;

  sprintf(output,"MSG:TUveD:%s:Topic was set by %s %i seconds ago.\n",tmpChannel->channel,tmpChannel->topicSetBy,time(NULL) - tmpChannel->topicSet);
  sSendData(userConnection,output);

  if (tmpChannel->modes[CHAN_TIME] == 1) {
    sprintf(output,"MSG:TUveD:%s:This channel has a time limit of %i seconds for songs.\n",tmpChannel->channel,tmpChannel->maxTime);
    sSendData(userConnection,output);
    sprintf(output,"MODE:%s:T:1:%i\n",tmpChannel->channel,tmpChannel->maxTime);
    sSendData(userConnection,output);
    }
  else {
    sprintf(output,"MODE:%s:T:0\n",tmpChannel->channel);
    sSendData(userConnection,output);
    }

  if (tmpChannel->modes[CHAN_QUEUE] == 1)
    sprintf(output,"MODE:%s:Q:1\n",tmpChannel->channel);
  else
    sprintf(output,"MODE:%s:Q:0\n",tmpChannel->channel);
  sSendData(userConnection,output);

  if (tmpChannel->modes[CHAN_RANDOM] == 1)
    sprintf(output,"MODE:%s:R:1\n",tmpChannel->channel);
  else
    sprintf(output,"MODE:%s:R:0\n",tmpChannel->channel);
  sSendData(userConnection,output);

  sprintf(output,"MODE:%s:A:%i\n",tmpChannel->channel,tmpChannel->modes[CHAN_RATING]);
  sSendData(userConnection,output);

  sprintf(output,"MODE:%s:C:%i\n",tmpChannel->channel,tmpChannel->modes[CHAN_CLASS]);
  sSendData(userConnection,output);
    

  writeLog(2,"Added user: %s to Channel: %s\n",userConnection->userInfo.username,channel);
  pthread_mutex_unlock(&chanMutex);

  return(0x0);
  }

tuveChanList_t *findChan(const char *channel) {
  tuveChanList_t *tmpChannel = 0x0;

  assert(channel);

  pthread_mutex_lock(&chanMutex);

  for (tmpChannel = channels;tmpChannel != 0x0;tmpChannel = tmpChannel->next) {

    if (!strcasecmp(tmpChannel->channel,channel)) {
      pthread_mutex_unlock(&chanMutex); 
      return(tmpChannel);
      }
    }

  pthread_mutex_unlock(&chanMutex);
  return(0x0);
  }

/*
 *  Add A Channel To The Global Channel List
 */
tuveChanList_t *addChan(const char *channel) {
  tuveChanList_t *tmpChannel = 0x0;

  pthread_mutex_lock(&chanMutex);

  channelCount++;

  if (channels == 0x0) {
    channels = (tuveChanList_t *)calloc(1,sizeof(tuveChanList_t));
    channels->next = 0x0;
    channels->prev = 0x0;
    channels->users = 0x0;
    channels->modes[CHAN_QUEUE] = 0x1;
    channels->modes[CHAN_RATING] = 0x2;
    channels->modes[CHAN_CLASS] = 0x1;
    sprintf(channels->channel,channel);
    sprintf(channels->topic,"No Topic Set");
    sprintf(channels->topicSetBy,"TUveD");
    channels->topicSet = time(NULL);
    sprintf(channels->videoChanTitle,"No Video");
    sprintf(channels->videoFile,"NA");
    channels->videoEnd = 0x0;
    writeLog(2,"ADDED CHAN1\n");
    tmpChannel = channels;
    }
  else {
    tmpChannel = (tuveChanList_t *)calloc(1,sizeof(tuveChanList_t));
    sprintf(tmpChannel->channel,channel);
    sprintf(tmpChannel->topic,"No Topic Set");
    sprintf(tmpChannel->topicSetBy,"TUveD");
    tmpChannel->topicSet = time(NULL);
    sprintf(tmpChannel->videoChanTitle,"NoVideo");
    sprintf(tmpChannel->videoFile,"NA");
    tmpChannel->videoEnd = 0x0;
    tmpChannel->next = channels;
    tmpChannel->prev = 0x0;
    tmpChannel->users = 0x0;
    tmpChannel->modes[CHAN_QUEUE] = 0x1;
    tmpChannel->modes[CHAN_RATING] = 0x2;
    tmpChannel->modes[CHAN_CLASS] = 0x1;
    channels->prev = tmpChannel;
    channels = tmpChannel;  
    writeLog(2,"ADDED CHAN2\n");
    }

  pthread_mutex_unlock(&chanMutex);

  return(tmpChannel);
  }

int tuveSendAllInUsersChans(myConnections_t *userConnection,char *output) {
  tuveUserChans_t *tmpChans = userConnection->userInfo.chans;

  for (;tmpChans != 0x0;tmpChans = tmpChans->next) {
    tuveSendAllInChan(tmpChans->channel,0x0,output);
    }
  return(0x0);
  }

int tuveSendAllInChan(const char *channel,myConnections_t *userConnection,char *output) {
  tuveChanList_t *tmpChannel = 0x0;
  tuveUserList_t *tmpUsers   = 0x0;

  tmpChannel = findChan(channel);

  if (tmpChannel == 0x0) {
    writeLog(1,"findChan Failed!\n");
    return(0x1);
    }


  //Dont see why i need a thread lock here

  tmpUsers = tmpChannel->users;

  for (;tmpUsers != 0x0;tmpUsers = tmpUsers->next) {
    if (userConnection == 0x0)
      sSendData(tmpUsers->user,output);
    else if (strcasecmp(tmpUsers->user->userInfo.username,userConnection->userInfo.username))
      sSendData(tmpUsers->user,output);
    }
  
  return(0x0); 
  }

int tuveSetTopic(myConnections_t *userConnection,char *chan,char *topic) {
  char output[1024];
  tuveChanList_t *tmpChannel = 0x0;

  tmpChannel = findChan(chan);

  if (tmpChannel == 0x0) {
    writeLog(1,"findChan Failed: SetTopic\n");
    return(0x1);
    }

  strncpy(tmpChannel->topic,topic,128);
  sprintf(output,"TOPIC:%s:%s\n",chan,tmpChannel->topic);
  tuveSendAllInChan(chan,0x0,output);
  sprintf(output,"MSG:TUveD:%s:%s has set the topic to: %s\n",chan,userConnection->userInfo.username,tmpChannel->topic);
  tuveSendAllInChan(chan,0x0,output);

  tmpChannel->topicSet = time(NULL);
  sprintf(tmpChannel->topicSetBy,userConnection->userInfo.username);

  return(0x0);
  }

int tuveKick(char *by,char *chan,char *nick,char *msg) {
  tuveChanList_t *tmpChannel = 0x0;
  myConnections_t *userConnection = 0x0;
  char output[1024];

  tmpChannel = findChan(chan);

  if (tmpChannel == 0x0) {
    writeLog(1,"findchan Failed: Kick\n");
    return(0x1);
    }

  userConnection = findNick(nick);

  if (userConnection == 0x0) {
    writeLog(1,"findNick Failed: Kick\n");
    return(0x1);
    }

  sprintf(output,"KICK:%s:%s:%s\n",chan,by,msg);
  sSendData(userConnection,output);


  nick = userConnection->userInfo.username;

  if (tuveRemoveFromChanList(chan,userConnection) == 0x1)
    writeLog(0,"ERROR: Can not remove %s from %s\n",userConnection->userInfo.username,chan);
  if (tuveDelChan(chan,userConnection) == 0x1)
    writeLog(0,"ERROR: Can not remove %s from %s's List\n",chan,userConnection->userInfo.username);


  sprintf(output,"MSG:TUveD:%s:%s has been kicked by %s, Reason: %s\n",chan,nick,by,msg);
  tuveSendAllInChan(chan,0x0,output);

  sprintf(output,"PART:%s:%s\n",chan,nick);
  tuveSendAllInChan(chan,0x0,output);

  writeLog(0,"Kicked %s\n",output);

  tuveChanJoin("#doghouse",userConnection);

  return(0x0);
  }

int tuveBan(const char *channel,const char *nick) {
  char output[1024];
  tuveChanList_t *tmpChannel = 0x0;
  myConnections_t *userConnection = 0x0;
  int i = 0x0;

  tmpChannel = findChan(channel);

  if (tmpChannel == 0x0) {
    writeLog(1,"findchan Failed: Ban\n");
    return(0x1);
    }

  userConnection = findNick(nick);
  sSendData(userConnection,"BAN\n");

  if (userConnection == 0x0) {
    writeLog(1,"nick Filed: Ban\n");  
    return(0x1);
    }

  for (i = 0x0;i < MAX_BANS;i++) {
    if (tmpChannel->bans[i] == 0x0) {
      tmpChannel->bans[i] = userConnection->userInfo.uid;
      break;
      }
    }

  sprintf(output,"MSG:TUveD:%s:%s has been banned\n",channel,userConnection->userInfo.username);
  tuveSendAllInChan(channel,0x0,output);

  return(0x0);
  }

int tuveUnBan(const char *channel,const char *nick) {
  char output[1024];
  tuveChanList_t *tmpChannel = 0x0;
  myConnections_t *userConnection = 0x0;
  int i = 0x0;

  tmpChannel = findChan(channel);

  if (tmpChannel == 0x0) {
    writeLog(1,"findchan Failed: Ban\n");
    return(0x1);
    }

  userConnection = findNick(nick);

  if (userConnection == 0x0) {
    writeLog(1,"nick Filed: Ban\n");
    return(0x1);
    }

  for (i = 0x0;i < MAX_BANS;i++) {
    if (tmpChannel->bans[i] == userConnection->userInfo.uid) {
      tmpChannel->bans[i] = 0x0;
      break;
      }
    }

  sprintf(output,"MSG:TUveD:%s:%s has been unbanned\n",channel,userConnection->userInfo.username);
  tuveSendAllInChan(channel,0x0,output);

  return(0x0);
  }

int tuveVerifyBan(const char *channel,const char *nick) {
  tuveChanList_t *tmpChannel = 0x0;
  myConnections_t *userConnection = 0x0;
  int i = 0x0;

  tmpChannel = findChan(channel);

  if (tmpChannel == 0x0) {
    writeLog(1,"findchan Failed: Ban\n");
    return(0x1);
    }

  userConnection = findNick(nick);

  if (userConnection == 0x0) {
    writeLog(1,"nick Filed: Ban\n");
    return(0x1);
    }

  for (i = 0x0;i < MAX_BANS;i++) {
    if (tmpChannel->bans[i] == userConnection->userInfo.uid) {
      return(0x1);
      }
    }

  return(0x0);
  }