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;
}
|