Viewing topic:Question about creating users for an IRC bot.
Page: 1 | 2
Topic post 15-12-2007 - 9:11
Hello, I gave your tutorial a read, and must say it's by far the best I've found for a PHP coded IRC bot.

I have a bot that I made using basically the same setup you have, except I'm using a config.ini file to hold some of the information: server, port, name, nick, pass, channel etc.

I've been looking around, and have yet to find a decent explanation on how to make a user system for a bot. Meaning that I would like it so only I have main control of the bots functions, and I'm able to add other users with certain access levels.

I've been wracking my brain for the past couple of days trying to come up with a good way to do this. Now, I'm extremely new to PHP, but I've read through many tutorials, and am starting to get a grip on it.

The best thing I could come up with so far, is to use the persons hostmask for the bot to recognize them, but I'm unsure if this is a good way to go about it.

Any help, or tips you can give are definitely appreciated.

Thanks guys, and awesome site. Now, I'm off to read more of your tutorials. =]
Topic post 15-12-2007 - 10:48
Hey Jalkson!

Thanks for the compliments .

About the user recognition, using the hostname like you said is the way to go. What i did for my bot is created a table with all the hostnames (inc nick) in it who have admin access.

This way you can do it different, you can save the hostname, and in a second row you can set his admin level.

Each time a user says something, just quickly check his user level (is he has any) and now you know what he can, and what he can't do.

This is how i did it:

code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

<?php
 
// Bot.php
 
		/**
		* Store all the admin's in a variable
		*/
		$admin1 = mysql_query("SELECT * FROM admin&quot;);
		$admin = "";
		while ($admin2 = mysql_fetch_assoc($admin1)){
			$admin .= $admin2['admin']." ";
		}	
 
 
		/**
		* Extract the hostname of posters
		*/
		preg_match('/^:(.*?)!(.*?)$/i', $ex[0], $matches);
		$hostname = "!".$matches[2];
		$username = $matches[1];
 
 
// Functions.php
 
function is_admin($hostname){
	global $admin;
	$pos = strpos($admin, $hostname);
	if ($pos === FALSE){
		return FALSE;
	}else{
		return TRUE;
	} 
 
}
 
?>
 


It's quite old code, and it's very ugly. But it works good enough.

Let me know if you have other problems.

(Notice that the code BB is wrong, at the end of some lines the quotes are turned into html code, this will soon be fixed with the new backend... Sorry!)
Topic post 16-12-2007 - 19:32
I'm not sure I understand exactly how to do it. What I've done so far with the irc bot tutorial is the most I've ever done with PHP.

If you get any free time, maybe you could elaborate on it a bit. I'm also in your IRC channel, since I'm always on IRC when I'm on the computer.

Also, this error is always present.

Notice: Undefined offset: 3 in crogram fileseasyphp1-8wwwjbot.php on line 54

Line 51 is :

$command = str_replace(array(chr(10), chr(13)), '', $ex[3]);

I know it's the $ex[3] offset, I'm just not sure how to make it stop giving me the notice.

I'll keep fooling with it, maybe I'll get lucky. :P

*Edit

I think my main issue is not being able to figure out how to get something sent from the server, and saving it as a variable.

Such as, right now just to mess around and figure stuff out, I'm trying to make a command @join #channel. I can't seem to figure out how to get the bot to take the channel name and use it to join the channel. I can easily setup a command to join a specific channel, but theres no way to tell what channel people would have it join.

I tried:

$channel = str_replace(array(chr(10), chr(13)), '', $ex[4]);

if ($command == ":".$config['prefix']."join ".$channel."n"{
fputs($con['socket'], "join".$channel. "n";
}

Though, I'm about 99% sure that's way off. I'm really stuck on this, so any help is much appreciated. =]
Topic post 17-12-2007 - 09:10
Quote:


[16-12-2007 19:32] Jalkson wrote:

$channel = str_replace(array(chr(10), chr(13)), '', $ex[4]);

if ($command == ":".$config['prefix']."join ".$channel."n"{
fputs($con['socket'], "join".$channel. "n";
}




if ($command == ":".$config['prefix']."join ".$channel."n"{

This looks a bit weird, let me search my code...

code
1
2
3
4
5

if ($ex[3] == ":~join&quot;){	
	if(isset($ex[4])){
		fputs($socket, "JOIN :".$ex[4]);
	}
}
 


I used this code. Can you try it?

(Normally i have an admin check with it, but i cut it out for you to edit it to your needs.)
Topic post 18-12-2007 - 02:41
Sorry, I just realized you answered pretty much all of my questions in the comments on the tutorial. :[

Well, what you gave me works just fine for saving the username(I haven' tried the hostname just yet).

The only issue I'm having currently, is the same NOTICE error I was getting before.

Notice: Undefined offset: 3 in program files
easyphp1-8www jbot.php on line 54

Line 54 is :

$command = str_replace(array(chr(10), chr(13)), '', $ex[3]);

I know it's the $ex[3] offset, I'm just not sure how to make it stop giving me the notice.

Now, I also get it with the new code you gave me,

preg_match('/^.*?)!(.*?)$/i', $ex[0], $matches);
$hostname = "!".$matches[2];
$username = $matches[1];

only now it's saying 2, 1, and the 3. Do you happen to know a way to have it stop giving me these notices?
Topic post 18-12-2007 - 08:03
You can stop PHP notices/warnings etc by adding a @ before the function.
Eg.

$this = @somefunction('arg1');

This should do the trick.
Topic post 18-12-2007 - 11:01
Thank you very much. I appreciate all your help. =]

I would love to see some more tutorials on this subject, maybe some type of addons. I can't think of anything specific at the moment, but if I do I'll let you know.

Thought I would post this for you to see. As you can see, I haven't quite figured out the admin system yet. :P

I really haven't done much customization at all, though I'll figure it out soon.

code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

<?php
/*
Jbot Created by Jalkson
Special thanks to Jim @ combined-minds.net
*/
 
   //disable the time limit
    set_time_limit(0);
 
   //Define your config variables
    $config = parse_ini_file("conf.ini&quot;);
    $serv = $config['serv'];
    $port = $config['port'];
    $name = $config['name'];
    $nick = $config['nick'];
    $host = $config['host'];
    $chan = $config['chan'];
    $pass = $config['pass'];
    $p = $config['prefix'];
 
   //Define and establishing a connection
    $server = fsockopen($config['serv'],$config['port']);
 
   //Telling the server your name/nick
    fputs($server,"USER ".$config['name']. "n&quot;);
    fputs($server,"NICK ".$config['nick']. "n&quot;);
 
   //Identifying your name
    fputs($server,"IDENTIFY ".$config['pass']."n&quot;);   
 
	usleep(500);	
 
   //Joining chosen channel
    fputs($server,"JOIN ".$config['chan']. "n&quot;);
 
   //Starting the loop **
    while(1) {
 
   //Setting the allotted data usage.
    while($data = fgets($server, 128)) {
 
	   echo nl2br($data);
	   flush();
 
   //Explode the data
    $ex = explode(' ', $data);
 
   //Replying to PING
    if($ex[0] == "PING&quot;){
       fputs($server,"PONG ".$ex[1]."n&quot;);
    }
 
   //Stores Hostname, and Username in variables
    preg_match('/^:(.*?)!(.*?)$/i', $ex[0], $matches);
     $hostname = "!".$matches[2];
     $username = $matches[1];
 
 
   //Setting the command line
    $command = str_replace(array(chr(10), chr(13)), '', $ex[3]);
 
 
   //die command
    if($command == ":".$p."die&quot;) {
	   fputs($server,"PRIVMSG ".$ex[2]." DIES n&quot;);
	   die();
	   }
 
   //join command
    if($command == ":".$p."join&quot;) {
	   fputs($server,"JOIN ".$config['chan']. "n&quot;);
	   }
 
   //Attempting to start on some sort of login system
 
 
	  }
   //** This last } ends the loop.  Keep everything else above it
    }	 
?>
 


code
1
2
3
4
5
6
7
8
9

[config]
host = RmRevolution.com
serv = irc.acidchat.net
port = 6667
chan = #rmrevolution
name = Jbot RmRevolution.com Jbot :Jbot
nick = Jbot
pass = 
prefix = @
 
Topic post 18-12-2007 - 15:36
Looks good already!

Some little things, when using your @die function, use the IRC command for quiting, this is cleaner

code
1

QUIT :And here your reason
 


The reason doesn't always work, but a normal quit is still nicer to look at.

Also you made new variables for the config data, but you still use config['bla'] in stead of the variables. Although config['bla'] looks nicer, it's kind of useless to make the variables now.



Are you intressted in my code? It's very simple (its 3 years old wehehe) but has quite much functionallity, maybe you can use that for your own bot.
Topic post 20-12-2007 - 09:19
I've been looking over the code you posted, I'm just having a hard time understanding exactly what it's doing. Also, I noticed it says something about MySQL, I don't plan on using any MySQL. I'm not sure if it's needed for something like this, but if I can, I'd rather not use it.

As I've mentioned, I'm still a bit new.

As for the variables and the config, I just started using the parsing, and was a bit confused how it worked. Though, it's funny, about 20 minutes ago, before I read this, I went through and changed them. :P

The quit message, is an awesome idea. I actually hadn't thought of that, it's much cleaner.
Topic post 20-12-2007 - 10:10
Well if you don't plan on using MySQL i thought of something else. Might not work that well but it's better than nothing.

Im at school so i can't test anything (can only use port 80 and 21), but ill try to write code without fail xD

First make an array to store the admins in

code
1

$admins = array('Jim', 'Nick');     // Use the nicknames which you use in IRC
 


Then when you have a function only ment for admins use:

code
1
2
3
4
5
6
7

<?php
// The in_array function checks if a value exists in the array. 
// $nick should hold the nick of the person who's trying to say something, and the second holds the array of all admins.
if(in_array($nick, $admins)) {
    // Do stuff
}
?>
 


This now works with Nicknames so it's easier to follow. Of course it's better if you would use hostnames in stead of nicknames.

Understand?

Topic post 20-12-2007 - 10:22
Yes, that's actually very simple.

So, is it not possible to use hostnames without mysql? Or am I misunderstanding that part.

Also, the snippet of code you gave me to store the hostname/nickname from irc doesn't seem to work with hostname.

Unless I'm actually wrong about which is the hostname, which is
possible. :[
Topic post 20-12-2007 - 10:36
No the hostname has nothing to do with MySQL actually.

What about the hostname snippet you don't understand??
Topic post 20-12-2007 - 10:43
I understand it just fine, it just doesn't seem to recognize the hostname when I try to use it in the code.

I tried doing something like

code
1
2
3

    if($hostname == "@adsl-71-141-89-144.dsl.snfc21.sbcglobal.net&quot;) {
	   fputs($server,"PRIVMSG ".$ex[2]." Hi Nick n&quot;);
	   } 
 


And it does nothing.
Topic post 20-12-2007 - 11:04
Hmm what does the hostname variable hold? (echo it)


And from now on login with Nick
Topic post 21-12-2007 - 06:08
I tried a simple command to have it print the hostname.

code
1
2
3

if($command == ":".$p."print&quot;) {
   echo $hostname
  }
 


Yet, it doesn't show anything when I use the command. I'm not very familiar with the echo/print commands.

This is actually an issue for my current command.

$time = date("l, F j, Y, g:i a";

Is for a command I intend to use, "!time", though I can't seem to figure out how to have it echo the variable.

I tried this without very much luck. It says the time/date in the browser, but not in the channel. Thus, you see my issue. :P

code
1
2
3

    if($command == ":".$p."time&quot;) {
	   fputs($server, "PRIVMSG ".$ex[2]. print ($time));
	   }
 


Sorry I'm asking so many questions, I really do try to figure this out on my own. XD

Also, thank you for the name change. =]

Here's my lame attempt at trying to use your join command for a kick command. I figured it would work the same. :P

I was wrong. XD

code
1
2
3
4
5
6
7

       if($username == "Jalkson&quot;) {
	 if($ex[3] == ":".$p."kick&quot;) {
	 if(isset($ex[4])){
	  fputs($server, "KICK :".$ex[4]);
	  }
     }
    }  
 


I'm still working on it, so hopefully I'll figure it out soon.

Oh, got the kick working. :] I simply forgot the parameters for kick. Once I get it all coded correctly, I'll post it up. It works just fine as long as I input the parameters manually into the code such as
code
1
2
3
4
5
6
7

if($username == "Jalkson&quot;) {
	 if($ex[3] == ":".$p."kick&quot;) {
	 if(isset($ex[4])){
	  fputs($server, "KICK #channel :".$ex[4]."n&quot;);
	  }
     }
    }  
 


I just can't get it to accept any channel the bot is in with high enough access, or a comment.

So, I just do @kick user and it will kick them. When I would like it to be @kick user comment, and have it show the reason.

I'll continue working.

Sorry, the post is extremely long. Once I figure it out, I'll edit most of this out, and just post the working code. :P
Topic post 21-12-2007 - 10:47
It's very weird that the hostname code isn't working :S

Can you post some values of $ex[0] (so the line that contains the nick and host) so we can build a regexp around it.
Topic post 21-12-2007 - 19:00
It might just be because I'm tired, but I'm not sure what you're asking for.

This?

:Jalkson!hithar@Acidchat-B6274BF1.dsl.snfc21.sbcglobal.net JOIN :#rmrevolution

Haha, sorry I'm really confused at the moment.
Topic post 21-12-2007 - 21:16
Quote:


[21-12-2007 19:00] Nick wrote:

:Jalkson!hithar@Acidchat-B6274BF1.dsl.snfc21.sbcglobal.net JOIN :#rmrevolution


preg_match('/^.*?)!(.*?)$/i', $ex[0], $matches);
$hostname = "!".$matches[2];
$username = $matches[1];

Hmm i see.. The $hostname variable should now contain:
!hithar@Acidchat-B6274BF1.dsl.snfc21.sbcglobal.net

The preg_match uses a technique called Regular expressions. This (old) regexp of mine isn't 100% accurate when it comes to the hostname. My Regexp takes everything followed by the first "!" as the hostname (because everything before the first ! is the nickname), while everything behing the "@" should be the hostname.

This is no problem, i won't bore you with difficult technical stuff, but try "!hithar@Acidchat-B6274BF1.dsl.snfc21.sbcglobal.net" to check the hostname.
Topic post 21-12-2007 - 21:58
Believe me, It's not boring. :P

I'll try that.

Also, I found something that's slightly interesting to me, but I wanted to get your opinion on it. I stumbled upon this while searching the net for some info on PHP and irc bots.

http://pear.php.net/package/Net_SmartIRC/

Have you had any experience with it? If so, do you recommend it? I'm not really sure how to use it, and am a little worried about trying to use it. Seeing as how I'm sure I'd have to rewrite the entire code for the bot.

I've barely heard of PEAR, so I'm not sure what it is, or how it works?

Edit*

After just trying to read how to install it my head hurts.

I think I might just stick to what I already have, and continue that.

My current frustration lies in creating a code that will send a message to the channel welcoming the user when they join.

Since the bot sees

:Jalkson!hithar@Acidchat-B6274BF1.dsl.snfc21.sbcglobal.net JOIN :#rmrevolution

when someone joins, and $ex[2] is the channelname, I figured $ex[1] would be JOIN. Thus, I tried this code

code
1
2
3
4

   //Autogreet
    if($ex[1] == "JOIN &quot;) {
	 fputs($server, "PRIVMSG ".$ex[2]." Hello %nick, welcome to %chan! n&quot;);
	 }
 


Though, not much to my surprise, it isn't working. :P

Also,

Quote:


[18-12-2007 08:03] Jim wrote:
You can stop PHP notices/warnings etc by adding a @ before the function.
Eg.

$this = @somefunction('arg1');

This should do the trick.


I don't really understand how that works. Could you write an example of how you would stop the notice for the $ex[3] notice?

Sorry about asking so many questions. You can tell me to stop at anytime. :P
Topic post 22-12-2007 - 12:03
Quote:


[21-12-2007 21:58] Nick wrote:
Believe me, It's not boring. :P

I'll try that.

Also, I found something that's slightly interesting to me, but I wanted to get your opinion on it. I stumbled upon this while searching the net for some info on PHP and irc bots.

http://pear.php.net/package/Net_SmartIRC/

Have you had any experience with it? If so, do you recommend it? I'm not really sure how to use it, and am a little worried about trying to use it. Seeing as how I'm sure I'd have to rewrite the entire code for the bot.

I've barely heard of PEAR, so I'm not sure what it is, or how it works?

Edit*

After just trying to read how to install it my head hurts.

I think I might just stick to what I already have, and continue that.

My current frustration lies in creating a code that will send a message to the channel welcoming the user when they join.

Since the bot sees

:Jalkson!hithar@Acidchat-B6274BF1.dsl.snfc21.sbcglobal.net JOIN :#rmrevolution

when someone joins, and $ex[2] is the channelname, I figured $ex[1] would be JOIN. Thus, I tried this code

code
1
2
3
4

   //Autogreet
    if($ex[1] == "JOIN &quot;) {
	 fputs($server, "PRIVMSG ".$ex[2]." Hello %nick, welcome to %chan! n&quot;);
	 }
 


Though, not much to my surprise, it isn't working. :P





Hmm, have you made sure the $ex[2] code is cleared from the r and n? It's about the str_replace(array(... stuff. Normally the last of the $ex would have r or n (or a combination) at the end of this. A r and n is given at the end of a line to indicate it's the end of the line. So when you don't strip it of the $ex variables you will end up with some protocol like this:

PRIVMSG #channeln :Hi Jim!n

Which is wrong.

Use it like this:

code
1
2
3
4
5
6
7
8
9
10
11

 
   // Clean the n and r
   $channel = str_replace(array(chr(10), chr(13)), "", $ex[2]);
 
   // But the ex2 also had a : before the channel, lets remove it
   $channel = substr($channel, 1);
 
   //Autogreet
    if($ex[1] == "JOIN &quot;) {
	 fputs($server, "PRIVMSG ".$channel." :Hello ".$username.", welcome to ".$channel."! n&quot;);
	 }
 


First we'll remove the n and r (the chr function returns ASCII characters.. Need explenation? )

Second is removing the : before the channel, look at the JOIN protocol you gave above and you'll see a : is in front. Well remove that also. Substr takes all text after the first character. (check php.net for that one, its a handy function)

Third, notice the ":" before the start of the text in the fputs which you forgot.

This piece of code should work fine. It might not be the most clean, but it works..

About the PEAR framework. It's a well-known framework which has allot of nice things, like IRC. It also has stuff like FTP connections and much more stuff.

You can use the IRC framework, but it's just much more fun to create your own bot from scratch. You are now learning a hellot of theory behind networking/sockets. Also you are (probablly?) learning your first Protocol. And it's fun to learn protocols, so you know what you are actually sending over the net.

IMO, you can better create your own IRC framework by learning the ins and outs about Object Orientated Programming (OOP). You can read some stuff about it on our tutorial section. But i first recommend you to just continue with this bot, and by the time you are experienced with PHP and the IRC protocol you should create your own framework.

Btw, we seriously need bigger textboxes :P

Oh and another BTW, you are a good guy (i wanted to say kid, but your older XD) mail me at jim at combined-minds.net if you need some direct help via msn or irc.
Topic post 22-12-2007 - 16:57
Ah, so I was somewhat on the right track.

I never thought to remove the newline, and carriage return and use $channel.

Yeah, I gave PEAR a look through, but decided I'd rather do it the way I have been. One of the main reasons I started the bot was because I'm on IRC constantly, but also because I've been very curious to learn PHP the past few weeks. OOP is keeping my interest peaked, and also giving me headaches. :P

Substr looks to be very useful, I'll have to read up on that when I get a chance.

Thank you very much.

Also, I sent you an email. =]
Topic post 24-12-2007 - 02:00
Sorry for posting again, but it's been past 24 hours and I have updates.

I was able to get the autogreet working just fine, thanks.

Now I'm really starting to work on an access system, and antiflood/spam.

I've figured out a way for the access system, but I'll let you see it once it's finished. :P

I'm sort of stuck on the anti-flood/anti-spam thing though.

What I would like it to do is, if a person says 4 or more lines of text in under 3 seconds they get kicked.

Any advice?
Topic post 24-12-2007 - 11:57
Hmm thats a difficult one. The first thing what i'm thinking about is creating an array for all users and record their last 10 lines or so, and at the end of the while loop check if users' lines are too close to eachother.

Quite a difficult thing to do (on a good way)
Topic post 04-01-2008 - 10:43
Its been a while... Were you able to create it? (or too busy with your SMF template? )
Topic post 08-02-2008 - 03:52
Ah, I actually haven't played with my bot in a while. Though I have been thinking about bringing it out again. :P

Page: 1 | 2 Reply Reply to topic

©Copyrights Combined Minds. All rights reserved 2006 - 2008 : Disclaimer
Realized by www.Minna-Media.com