Plan 9 from Bell Labs’s /usr/web/sources/contrib/maht/inferno/appl/cmd/Ltheme/irc.b

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


implement Ircdata;

include "irc.m";

include "sys.m";
	sys : Sys;

include "string.m";
	str : String;

# from hash.b
hashit(s:string, n:int):int
{
	h := 0;
	m := len s;
	for(i:=0; i<m; i++){
		h = 65599*h+s[i];
	}
	return (h & 16r7fffffff) % n;
}

dump_array(indent: string, a: array of string) 
{
	for(i := 0; i < len a; i ++) {
		sys->print("%s[%d] = \"%s\"\n", indent, i, a[i]);
	}
}

new_users(size:int): ref Users
{
	return ref Users(array[size] of list of ref User);
}

new_post(data : string) : ref Post
{	
	post : Post;
	fluff_list : list of string;

	sys = load Sys Sys->PATH;
	str = load String String->PATH;

	sys->print(">>NEW_POST>>%s<<\n", data);
	
	if(data[0] == ':') {
		(post.issuing_nick, data) = str->splitl(data[1:], " ");
		data = data[1:];
	}

	(args, fluff) := str->splitl(data, ":");
	(nil, arg_list) := sys->tokenize(args, " ");
	if(len fluff > 0)
		(nil, fluff_list) = sys->tokenize(fluff[1:], " ");
	post.command = str->toupper(hd arg_list);
	arg_list = tl arg_list;
	post.args = array[len arg_list + len fluff_list] of string;
	i := 0;
	for(; arg_list != nil ; arg_list = tl arg_list)
		post.args[i++] = hd arg_list;
	for(; fluff_list != nil ; fluff_list = tl fluff_list)
		post.args[i++] = hd fluff_list;

	return ref post;
}


Post.print(post: self ref Post)
{
	sys = load Sys Sys->PATH;
	sys->print("Issuing nick: %s\n", post.issuing_nick);
	if(post.issuer == nil)
		sys->print("\tIssuer not fetched\n");
	else
		post.issuer.print();

	if(post.target == nil)
		sys->print("\ttarget not fetched\n");
	else
		post.target.print();

	sys->print("\t>>cmd %s\n",  post.command);
	dump_array("\t\t", post.args);
}

Users.add(users: self ref Users, nick: string): ref User
{
	existing := users.find(nick);
	if(existing != nil)
		return nil;
	user := ref User;
	user.nick = nick;
	user.logged_in = 0;
	user.registered = 1;

	j := hashit(nick,len users.u);
	users.u[j] = user :: users.u[j];

	return user.copy();
}

Users.find(users: self ref Users, nick : string): ref User
{
	user := user_ref(users, nick);
	if(user == nil)
		return nil;

	return user.copy();
}

user_ref(users: ref Users, nick : string): ref User
{
	j := hashit(nick,len users.u);
	for(q := users.u[j]; q!=nil; q = tl q){
		if((hd q).nick==nick) {
			return hd q;
		}
	}
	return nil;
}

Users.find_or_add(users: self ref Users, nick : string): ref User
{
	user := users.find(nick);
	if (user == nil) {
		user = users.add(nick);
	}
	return user;
}

Users.log_in(users: self ref Users, service: ref Service, nick : string) : ref User
{
	user := user_ref(users, nick);
	if(user == nil)
		return nil;
	user.logged_in = 1;
	service.out <-= sys->sprint(":%s PRIVMSG %s :you are now logged in", service.nick, nick);
	return users.find(nick);
}

Users.log_out(users: self ref Users, service: ref Service, nick : string)
{
	user := user_ref(users, nick);
	if(user == nil)
		return;
	user.logged_in = 0;
	service.out <-= sys->sprint(":%s PRIVMSG %s : %s logged you out", service.nick, service.nick, nick);
	service.out <-= sys->sprint("%s SVS2MODE %s -r+d 0", service.nick, nick); # unreal
}

Users.verify_password(users: self ref Users, nick, password : string) : int
{
	return password == "123";
}

User.copy(user: self ref User) : ref User
{
	u := ref User;
	u.nick = user.nick;
	u.logged_in = user.logged_in;
	return u;
}

User.print(user: self ref User)
{
	sys = load Sys Sys->PATH;
	sys->print("Nick: \"%s\"\n", user.nick);
	sys->print("logged in: \"%d\"\n", user.logged_in);
}

Services.find(services: self ref Services, name : string): ref Service
{
	for(srvs := services.s; srvs!=nil; srvs = tl srvs){
		if((hd srvs).name==name) {
			return hd srvs;
		}
	}
	return nil;
}

Services.add(services: self ref Services, nick : string, out : chan of string): ref Service
{
	str = load String String->PATH;
	service : ref Service;
	service = services.find(nick);
	if(service == nil) {
		service = ref Service;
		service.name = str->toupper(nick);
		service.nick = nick;
		service.out = out;
		service.c = array[27] of list of ref Command;  # 27 magic prime
		services.s = service :: services.s;
	}
	return service;
}


Service.add_command(service: self ref Service, name: string, func: ref Func) : ref Command
{
	if(service.c == nil) return nil;

	cmd : ref Command;
	cmd = service.find_command(name);
	if(cmd == nil) {
		cmd = ref Command;
		cmd.name = name;
		cmd.func = func;
		j := hashit(name, len service.c);
		service.c[j] = cmd :: service.c[j];
	} else {
		cmd.func = func;
	}

	return cmd;
}

Service.find_command(service: self ref Service, name: string) : ref Command
{
	if(service.c == nil)
		return nil;

	j := hashit(name, len service.c);
	for(cmds := service.c[j]; cmds!=nil; cmds = tl cmds){
		if((hd cmds).name==name) {
			return hd cmds;
		}
	}
	return nil;
}

identify(service: ref Service, users : ref Users, post:  ref Post) : int
{
	if(len post.args != 3) {
		service.out <-= sys->sprint(":%s PRIVMSG %s :usage IDENTIFY password ", service.nick, post.issuing_nick);
		return 0;
	}

	if(post.issuer == nil || !users.verify_password(post.issuer.nick, post.args[2])) {
		service.out <-= sys->sprint(":%s PRIVMSG %s :%s not registered / bad password", service.nick, post.issuer.nick, post.issuer.nick);
		return 0;
	}

	post.target = users.log_in(service, post.issuer.nick);
	return 1;	
}

nick(service: ref Service, users : ref Users, post:  ref Post) : int
{
	if(post.issuer == nil)
		return 0;

	user := user_ref(users, post.issuer.nick);
	if(user == nil)
		return 0;
	if(user.logged_in)
		users.log_out(service, post.issuer.nick);

	if(user.registered)
		service.out <-= sys->sprint(":%s PRIVMSG %s :this nick belongs to a registered user. To register see http://www.bangshortfilmfestival.com/new_account.html", service.nick, post.args[0]);

	users.add(post.args[0]);
	user.nick = post.args[0];
	return 1;
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.