#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "tuved.h"
int playCnt = 0;
int nextSong();
int chanMaint();
int tuveCMD_CMD(myConnections_t *userConnection,char *chan,char *data) {
char output[512];
char dMS[2] = {'-','+'};
char *cmd = 0x0;
char *cmdData = 0x0;
char *modeString = 0x0;
char *tmp = 0x0;
char *tmp2 = 0x0;
char *tok_last = 0x0;
tuveChanList_t *tmpChan = 0x0;
tuveUserList_t *tmpUser = 0x0;
MYSQL_RES *res = 0x0;
MYSQL_ROW row;
short dM = 0x0;
unsigned int i = 0x0;
if (data == 0x0)
return(0x1);
cmd = strtok_r(data," ",&tok_last);
cmdData = strtok_r(NULL,"\n",&tok_last);
if (cmd == 0x0)
return(0x1);
if (strcasecmp(cmd,"login") == 0x0) {
tok_last = 0x0;
tmp = strtok_r(cmdData," ",&tok_last);
tmp2 = strtok_r(NULL,"\n",&tok_last);
if ((tmp != 0x0) & (tmp2 != 0x0)) {
sprintf(output,"SELECT username,gid,uid FROM users WHERE username = '%s' AND password = '%s'",tmp,tmp2);
res = dbQuery(output,1);
if (res == 0x0) {
sSendData(userConnection,"MSG:TUveD:STATUS:Sorry I'm Having MySQL Troubles.");
}
else if (mysql_num_rows(res) == 1) {
sSendData(userConnection,"MSG:TUveD:%s:You have successfully logged in.",chan);
row = mysql_fetch_row(res);
sprintf(output,"INSERT INTO active (gid,uid,userid) VALUES(%s,%s,%lld)",row[1],row[2],userConnection->userInfo.uid);
dbQuery(output,0);
sSendData(findNick("TUveBOT"),"LOGIN:%s:%lld",userConnection->userInfo.username,userConnection->userInfo.uid);
if (atoi(row[1]) == 1) {
sprintf(output,"EMOTE:%s:STATUS:Is now an Evil Overlord!",userConnection->userInfo.username);
tuveSendAllInUsersChans(userConnection,output);
userConnection->userInfo.modes[USER_OVERLORD] = 1;
}
userConnection->userInfo.ident = 2;
}
else {
sSendData(userConnection,"MSG:TUveD:%s:You have failed login.",chan);
}
if (res != 0x0)
mysql_free_result(res);
}
} /* End login */
else if (tuveFindChanLevel(chan,userConnection,0) == 0) {
sSendData(userConnection,"MSG:TUveD:STATUS:You do not have permission to set channel mode.");
return(0x0);
} /* Commands Stop Here If You Channel Level Isn't >= 1 */
else if (strcasecmp(cmd,"pause") == 0x0) {
tuveSendAllInChan(chan,0x0,"PAUSE");
}
else if (strcasecmp(cmd,"resume") == 0x0) {
tuveSendAllInChan(chan,0x0,"RESUME\n");
}
else if (strcasecmp(cmd,"skip") == 0x0) {
if (cmdData != 0x0)
tmpChan = findChan(cmdData);
else
tmpChan = findChan(chan);
if (tmpChan != 0x0) {
if (tmpChan->vidClass != 7) {
tmpChan->videoEnd = 0x0;
tmpChan->count = MAX_COUNT;
}
}
}
else if (strcasecmp(cmd,"mode") == 0x0) {
tmpChan = findChan(chan);
if (cmdData != 0x0) {
tok_last = 0x0;
modeString = strtok_r(cmdData," ",&tok_last);
if (modeString[0] == '-')
dM = 0;
else if (modeString[0] == '+')
dM = 1;
else {
sSendData(userConnection,"MSG:TUveD:STATUS:Invalid Mode String.");
return(0x0);
}
for (i = 1;i < strlen(modeString);i++) {
switch(modeString[i]) {
case '-':
dM = 0;
break;
case '+':
dM = 1;
break;
case 'o':
case 'O':
tmp = strtok_r(NULL," ",&tok_last);
if (tmp != 0x0) {
if (tuveChanOp(chan,tmp,dM) == 0x0) {
sprintf(output,"MSG:TUveD:%s:%s Sets Mode %cO %s",chan,userConnection->userInfo.username,dMS[dM],tmp);
tuveSendAllInChan(chan,0x0,output);
}
}
else {
sSendData(userConnection,"MSG:TUveD:STATUS:Missing +O Opperators");
}
break;
case 'a':
case 'A':
tmp = strtok_r(NULL," ",&tok_last);
if (tmp != 0x0) {
tmpChan->modes[CHAN_RATING] = atoi(tmp);
sprintf(output,"MODE:%s:A:%i",tmpChan->channel,tmpChan->modes[CHAN_RATING]);
tuveSendAllInChan(chan,0x0,output);
}
break;
case 'c':
case 'C':
tmp = strtok_r(NULL," ",&tok_last);
if (tmp != 0x0) {
tmpChan->modes[CHAN_CLASS] = atoi(tmp);
sprintf(output,"MODE:%s:C:%i",tmpChan->channel,tmpChan->modes[CHAN_CLASS]);
tuveSendAllInChan(chan,0x0,output);
}
break;
case 'e':
case 'E':
if (dM == 0) {
tmpChan->modes[CHAN_EXCLUSIVE] = 0;
sprintf(output,"MSG:TUveD:%s:%s Sets Mode %cExclusive",chan,userConnection->userInfo.username,dMS[dM]);
tuveSendAllInChan(chan,0x0,output);
}
else {
sprintf(output,"SELECT oid FROM channels WHERE channel LIKE '%s'",tmpChan->channel);
res = dbQuery(output,1);
if (res == 0x0) {
sprintf(output,"MSG:TUveD:%s:Sorry I'm having SQL troubles today.",tmpChan->channel);
tuveSendAllInChan(tmpChan->channel,0x0,output);
}
else if (mysql_num_rows(res) == 0x0) {
sprintf(output,"MSG:TUveD:%s:Sorry this channel is not registered.",tmpChan->channel);
tuveSendAllInChan(tmpChan->channel,0x0,output);
}
else {
row = mysql_fetch_row(res);
tmpChan->modes[CHAN_EXCLUSIVE] = 1;
tmpChan->oid = atoi(row[0]);
sprintf(output,"MSG:TUveD:%s:%s Sets Mode %cExclusive",chan,userConnection->userInfo.username,dMS[1]);
tuveSendAllInChan(chan,0x0,output);
}
if (res != 0x0)
mysql_free_result(res);
}
sprintf(output,"MODE:%s:E:%i",tmpChan->channel,tmpChan->modes[CHAN_EXCLUSIVE]);
tuveSendAllInChan(chan,0x0,output);
break;
case 'r':
case 'R':
tmpChan->modes[CHAN_RANDOM] = dM;
sprintf(output,"MSG:TUveD:%s:%s Sets Mode %cRandom",chan,userConnection->userInfo.username,dMS[dM]);
tuveSendAllInChan(chan,0x0,output);
sprintf(output,"MODE:%s:R:%i",tmpChan->channel,dM);
tuveSendAllInChan(chan,0x0,output);
break;
case 'q':
case 'Q':
tmpChan->modes[CHAN_QUEUE] = dM;
sprintf(output,"MSG:TUveD:%s:%s Sets Mode %cQueue",chan,userConnection->userInfo.username,dMS[dM]);
tuveSendAllInChan(chan,0x0,output);
sprintf(output,"MODE:%s:Q:%i",tmpChan->channel,dM);
tuveSendAllInChan(chan,0x0,output);
break;
case 'X':
tmpChan->modes[CHAN_NOADS] = dM;
sprintf(output,"MSG:TUveD:%s:%s Sets Mode %cNo Advertisements",chan,userConnection->userInfo.username,dMS[dM]);
tuveSendAllInChan(chan,0x0,output);
sprintf(output,"MODE:%s:X:%i",tmpChan->channel,dM);
tuveSendAllInChan(chan,0x0,output);
break;
case 't':
case 'T':
if (dM == 1) {
tmp = strtok_r(NULL," ",&tok_last);
if (tmp != 0x0) {
tmpChan->modes[CHAN_TIME] = dM;
tmpChan->maxTime = atoi(tmp);
sprintf(output,"MSG:TUveD:%s:%s Sets Mode +Time Limit %s",chan,userConnection->userInfo.username,tmp);
tuveSendAllInChan(chan,0x0,output);
sprintf(output,"MODE:%s:T:%i:%s",tmpChan->channel,dM,tmp);
tuveSendAllInChan(chan,0x0,output);
}
}
else {
tmpChan->modes[CHAN_TIME] = dM;
sprintf(output,"MSG:TUveD:%s:%s Sets Mode %cTime Limit",chan,userConnection->userInfo.username,dMS[dM]);
tuveSendAllInChan(chan,0x0,output);
sprintf(output,"MODE:%s:T:%i",tmpChan->channel,dM);
tuveSendAllInChan(chan,0x0,output);
}
break;
case 'S':
if (dM == 0x1) {
for (tmpUser = tmpChan->users;tmpUser != 0x0;tmpUser = tmpUser->next) {
if (tmpUser->user == userConnection) {
tmpChan->nextUser = tmpUser;
}
}
}
else
tmpChan->nextUser = tmpChan->users;
tmpChan->modes[CHAN_SCHEDULED] = dM;
sprintf(output,"MSG:TUveD:%s:%s Sets Mode %cScheduled",chan,userConnection->userInfo.username,dMS[dM]);
tuveSendAllInChan(chan,0x0,output);
sprintf(output,"MODE:%s:S:%i",tmpChan->channel,dM);
tuveSendAllInChan(chan,0x0,output);
break;
default:
sSendData(userConnection,"MSG:TUveD:STATUS:Invalid Channel Mode");
break;
}
}
}
}
else if (strcasecmp(cmd,"queue") == 0x0) {
tmpChan = findChan(chan);
if (tmpChan == 0x0)
return(0x0);
sprintf(output,"MSG:TUveD:%s:Queue Order - ",userConnection->userInfo.username);
for (tmpUser = tmpChan->users;tmpUser != 0x0;tmpUser = tmpUser->next) {
if (tmpUser == tmpChan->nextUser)
sprintf(output,"%s(%s),",output,tmpUser->user->userInfo.username);
else if (tmpUser == tmpChan->nextUser->next)
sprintf(output,"%s[%s],",output,tmpUser->user->userInfo.username);
else
sprintf(output,"%s%s,",output,tmpUser->user->userInfo.username);
}
sSendData(userConnection,output);
}
else if (strcasecmp(cmd,"random") == 0x0) {
tmpChan = findChan(chan);
if (tmpChan == 0x0)
return(0x0);
if ((tmpChan->modes[CHAN_LIVE] == 0x1) || (tmpChan->vidClass == 7))
return(0x0);
sprintf(output,"SELECT artist,title,file,length,vid,classification,rating FROM videos WHERE status = 0 AND rating <= %i",tmpChan->modes[CHAN_RATING]);
if (tmpChan->modes[CHAN_EXCLUSIVE])
sprintf(output,"%s AND oid = %i",output,tmpChan->modes[CHAN_EXCLUSIVE]);
if (tmpChan->modes[CHAN_CLASS])
sprintf(output,"%s AND classification = %i",output,tmpChan->modes[CHAN_CLASS]);
res = dbQuery(output,1);
if (res == 0x0) {
sprintf(output,"MSG:TUveD:%s:Sorry I'm Have SQL Troubles Today.",chan);
tuveSendAllInChan(chan,0x0,output);
}
else if (mysql_num_rows(res) == 0x0) {
sprintf(output,"MSG:TUveD:%s:Sorry There Are No Videos Available At The Current Channel Settings.",chan);
tuveSendAllInChan(chan,0x0,output);
}
else {
mysql_data_seek(res,(random() % mysql_num_rows(res)));
row = mysql_fetch_row(res);
//sprintf(output,"UPDATE videos SET count = %i WHERE vid = %s",atoi(row[7])+1,row[4]);
//dbQuery(output,0);
tuveBotSetSong(chan,userConnection->userInfo.username,row[0],row[1],atoi(row[3]),row[2],atoi(row[5]),atoi(row[6]),atoi(row[4]));
}
if (res != 0x0)
mysql_free_result(res);
}
else if (strcasecmp(cmd,"rotatelog") == 0x0) {
writeLog(0,"Rotating Log File");
fclose(logFile);
sprintf(logFileName,"./logs/tuved.%i.log",time(NULL));
logFile = fopen(logFileName,"a");
writeLog(0,"Log Rotated");
}
else if (strcasecmp(cmd,"nextuser") == 0x0) {
sprintf(output,"MSG:TUveD:%s:The Next User is %s",chan,tmpChan->nextUser->user->userInfo.username);
tuveSendAllInChan(chan,0x0,output);
}
return(0x0);
}
void *tuveCMD_Thread(void *threadid) {
int tid;
MYSQL_RES *res = 0x0;
MYSQL_ROW row;
tid = (int)threadid;
writeLog(0,"Starting Bot Thread: [%d]\n", tid);
res = dbQuery("SELECT count FROM videos ORDER BY count ASC LIMIT 1",1);
row = mysql_fetch_row(res);
if (row)
playCnt = atoi(row[0]);
mysql_free_result(res);
while (1) {
sleep(5);
nextSong();
chanMaint();
}
pthread_exit(NULL);
} /* End tuveCMD_Thread() */
int chanMaint() {
tuveChanList_t *tmpChans;
time_t curTime = time(NULL);
int i = 0x0;
pthread_mutex_lock(&chanMutex);
for (tmpChans = channels;tmpChans != 0x0;tmpChans = tmpChans->next) {
for (i = 0;i < CHAN_MAX_BANS;i++) {
if ((tmpChans->bans[i][0] != 0x0) && (tmpChans->bans[i][1] < curTime))
tmpChans->bans[i][0] = 0x0;
}
}
pthread_mutex_unlock(&chanMutex);
return(0x0);
}
int tuveBotSetVideo(char *chan,char *nick,int vid) {
MYSQL_RES *res = 0x0;
MYSQL_ROW row;
char output[256];
sprintf(output,"SELECT artist,title,file,length,classification,rating,count FROM videos WHERE vid = %i",vid);
res = dbQuery(output,1);
if ((res == 0x0) || (mysql_num_rows(res) == 0x0)) {
sprintf(output,"MSG:TUveD:%s:Sorry I'm Have SQL Troubles Today.",chan);
tuveSendAllInChan(chan,0x0,output);
}
else {
row = mysql_fetch_row(res);
sprintf(output,"UPDATE videos SET count = %i WHERE vid = %i",atoi(row[6])+1,vid);
dbQuery(output,0);
tuveBotSetSong(chan,nick,row[0],row[1],atoi(row[3]),row[2],atoi(row[4]),atoi(row[5]),vid);
}
if (res != 0x0)
mysql_free_result(res);
return(0x0);
}
int
tuveBotSetSong(char *channel,char *nick,char *artist,char *title,int length,char *file,int class,int rating,int vid) {
tuveChanList_t *tmpChan;
char output[1024];
int min, sec;
songCount++;
playCount += length;
tmpChan = findChan(channel);
if (tmpChan->modes[CHAN_SCHEDULED] == 0x1)
goto jmpAhd;
if (tmpChan->modes[CHAN_TIME] == 0x1) {
if (length > tmpChan->maxTime) {
return(0x0);
}
}
if (tmpChan->modes[CHAN_RATING] < rating)
return(0x0);
if ((tmpChan->modes[CHAN_CLASS] != class) && (tmpChan->modes[CHAN_CLASS] != 0x0) && (class != 7))
return(0x0);
jmpAhd:
tmpChan->comDelay -= length;
tmpChan->vidClass = class;
min = length / 60;
sec = length % 60;
tmpChan->videoTime = length;
tmpChan->videoEnd = length + time(NULL) + VIDE_PAD_TIME;
tmpChan->vid = vid;
sprintf(tmpChan->videoFile,file);
if (nick[strlen(nick)-1] == 's')
sprintf(tmpChan->videoChanTitle,"%s' Pick -> <A HREF=\"event:%i\"><FONT COLOR=\"#8080FF\">[%s - %s]</FONT></A>",nick,vid,artist,title);
else
sprintf(tmpChan->videoChanTitle,"%s's Pick -> <A HREF=\"event:%i\"><FONT COLOR=\"#8080FF\">[%s - %s]</FONT></A>",nick,vid,artist,title);
sprintf(tmpChan->videoTitle,"%s - %s",artist,title);
sprintf(output,"CURPOS:%s:0:%s:%s:%i:%i",tmpChan->channel,file,tmpChan->videoTitle,length,vid);
writeLog(0,"[%s][%s]\n",output,channel);
tuveSendAllInChan(channel,0x0,output);
sprintf(output,"MSG:TUveD:%s:Playing %s (%d:%.2d)",channel,tmpChan->videoChanTitle,min,sec);
tuveSendAllInChan(channel,0x0,output);
/*
if (tmpChan->count != -1) {
if (tmpChan->nextUser != 0x0)
tmpChan->nextUser = tmpChan->nextUser->next;
if (tmpChan->nextUser == 0x0)
tmpChan->nextUser = tmpChan->users;
}
*/
tmpChan->count = MAX_COUNT;
return(0x0);
} // tuveBotSetSong()
int nextSong() {
char output[1024];
tuveChanList_t *tmpChans;
MYSQL_RES *res = 0x0;
MYSQL_ROW row;
time_t curTime;
short lC;
curTime = time(NULL);
pthread_mutex_lock(&chanMutex);
for (tmpChans = channels;tmpChans != 0x0;tmpChans = tmpChans->next) {
if ((tmpChans->modes[CHAN_LIVE] == 0x0) && (tmpChans->videoEnd < curTime)) {
/* Set point to starting user */
findUser:
if (tmpChans->modes[CHAN_SCHEDULED] == 0x1)
goto gotUser;
if ((tmpChans->modes[CHAN_NOADS] == 0) && (tmpChans->comDelay <= 0))
goto getCommercial;
//if (tmpChans->modes[CHAN_QUEUE] == 0x0) /* If Channel Has Queues Disabled Jump Right To Random */
// goto getRandom;
if (tmpChans->count == MAX_COUNT) {
lC = 0;
while (lC <= tmpChans->userCount) {
/* Reset Chan Counter */
tmpChans->count = 0x0;
if (tmpChans->nextUser == 0x0)
goto getRandom;
tmpChans->nextUser = tmpChans->nextUser->next;
/* Make sure we didn't go beyond the list */
if (tmpChans->nextUser == 0x0)
tmpChans->nextUser = tmpChans->users;
if (tmpChans->nextUser == 0x0)
goto sE;
if (((tmpChans->modes[CHAN_QUEUE] == 0x0) && (tmpChans->nextUser->chanLevel >= 1)) || (tmpChans->modes[CHAN_QUEUE] == 0x1))
if (tmpChans->nextUser->user->userInfo.queue == 0x1)
goto gotUser;
lC++;
}
}
else if (tmpChans->nextUser != 0x0)
goto gotUser;
/* Find A Random Song */
getRandom:
if (tmpChans->modes[CHAN_RANDOM] == 0x1) {
sprintf(output,"SELECT artist,title,file,length,vid,classification,rating,count,random_count FROM videos WHERE status = 0 AND rating <= %i",tmpChans->modes[CHAN_RATING]);
if (tmpChans->modes[CHAN_EXCLUSIVE])
sprintf(output,"%s AND oid = %i",output,tmpChans->oid); //tmpChans->modes[CHAN_EXCLUSIVE]);
if (tmpChans->modes[CHAN_CLASS])
sprintf(output,"%s AND classification = %i",output,tmpChans->modes[CHAN_CLASS]);
sprintf(output,"%s ORDER BY random_count ASC, RAND() LIMIT 1", output);
res = dbQuery(output,1);
if (res == 0x0) {
sprintf(output,"MSG:TUveD:%s:Sorry I'm Having SQL Troubles Today.",tmpChans->channel);
tuveSendAllInChan(tmpChans->channel,0x0,output);
}
else if (mysql_num_rows(res) == 0x0) {
sprintf(output,"MSG:TUveD:%s:Sorry Videos Matching The Channels Settings.",tmpChans->channel);
tuveSendAllInChan(tmpChans->channel,0x0,output);
}
else {
//mysql_data_seek(res,(random() % mysql_num_rows(res)));
row = mysql_fetch_row(res);
sprintf(output,"UPDATE videos SET random_count = %i WHERE vid = %s\n",atoi(row[8])+1,row[4]);
dbQuery(output,0);
tmpChans->count = MAX_COUNT;
tuveBotSetSong(tmpChans->channel,"TUveD",row[0],row[1],atoi(row[3]),row[2],atoi(row[5]),atoi(row[6]),atoi(row[4]));
}
if (res != 0x0)
mysql_free_result(res);
}
goto sE;
getCommercial:
tmpChans->comDelay = COM_DELAY;
getComAgain:
sprintf(output,"SELECT artist,title,file,length,vid,classification,rating,count FROM videos WHERE rating <= %i AND classification = 7 AND count <= %i",tmpChans->modes[CHAN_RATING],playCnt);
res = dbQuery(output,1);
if (res == 0x0) {
sprintf(output,"MSG:TUveD:%s:Sorry I'm Having SQL Troubles Today.",tmpChans->channel);
tuveSendAllInChan(tmpChans->channel,0x0,output);
}
else if (mysql_num_rows(res) == 0x0) {
playCnt++;
mysql_free_result(res);
goto getComAgain;
}
else {
mysql_data_seek(res,(random() % mysql_num_rows(res)));
row = mysql_fetch_row(res);
sprintf(output,"UPDATE videos SET count = %i WHERE vid = %s\n",atoi(row[7])+1,row[4]);
dbQuery(output,0);
tmpChans->count = MAX_COUNT;
tuveBotSetSong(tmpChans->channel,"TUveD",row[0],row[1],atoi(row[3]),row[2],atoi(row[5]),atoi(row[6]),atoi(row[4]));
}
if (res != 0x0)
mysql_free_result(res);
goto sE;
gotUser:
if (tmpChans->nextUser->user->userInfo.queue == 0x1) {
if (((tmpChans->modes[CHAN_QUEUE] == 0x0) && (tmpChans->nextUser->chanLevel >= 1)) || (tmpChans->modes[CHAN_QUEUE] == 0x1)) {
sSendData(tmpChans->nextUser->user,"GETVIDEO");
writeLog(0,"Need To Find Next Song For: %s, From User: %s\n",tmpChans->channel,tmpChans->nextUser->user->userInfo.username);
tmpChans->count++;
}
else if (tmpChans->modes[CHAN_SCHEDULED] == 0) {
tmpChans->count = MAX_COUNT;
goto findUser;
}
}
else if (tmpChans->modes[CHAN_SCHEDULED] == 0) {
tmpChans->count = MAX_COUNT;
goto findUser;
}
sE:
asm("nop");
}
}
pthread_mutex_unlock(&chanMutex);
return(0x0);
} /* End nextSong() */