Esempio n. 1
0
class Conf(object):
    __slots__ = [
        "target",
        "name",
        "health",
        "next_question",
        "defenders",
        "offenders",
        "question",
        "start_time",
        "registry",
        "cooldowns",
        "questions",
        "print_queue",
        "defeated_commands",
        "reward_person",
        "reward_timeout",
        "defeated_timeout",
        "cmd_request_sent",
        "reward_cmd",
        "reward_args",
        "police_notify_sent",
        "stat_cooldown",
    ]

    def __init__(self, target, name=None):
        self.target = target
        self.name = name if name else utils.randStr()
        self.health = logic.getSystemVitality(self.target)
        self.next_question = None
        self.start_time = None
        self.defenders = {}
        self.offenders = {}
        #        self.cooldowns = {}
        self.questions = logic.getQuestions(self.target)
        self.question = None
        self.registry = Registry()
        self.print_queue = Queue()
        self.defeated_commands = None
        self.defeated_timeout = None
        self.reward_person = None
        self.reward_timeout = None
        self.reward_cmd = None
        self.reward_args = None
        #        self.saved_message = None
        self.cmd_request_sent = None
        self.police_notify_sent = False
        self.stat_cooldown = None

    def sendPoliceNotify(self, target):
        if not self.police_notify_sent:
            msg = (
                u"From: %s\nTo: %s\nContent-type: text/plain;charset=utf-8\nSubject: WARNING! Target is under attack\n\nTarget: %s\nAttack time: %s"
                % (config.fromEmail, config.policeEmail, target, time.ctime())
            )
            msg = unicode(msg).encode("utf-8")
            s = smtplib.SMTP()
            s.connect(config.mailHost, config.mailPort)
            res = s.sendmail(config.fromEmail, config.policeEmail, msg)
            logging.info("police notify sent %s", res)
            self.police_notify_sent = True

    #     def onExit(self, person):
    #         self.cooldowns[person] = time.time() + logic.getCooldownOnExit(person, self.target)

    #     def onEnter(self, conn, person, nickname):
    #         if self.cooldowns.get(person, 0) > time.time():
    #            utils.sendKick(conn, self.name, [nickname], u"Отдохни!")

    @utils.protect
    def onPresence(self, conn, person, nickname, alive):
        if alive:
            logging.info(u"%s comes to %s", person, self.target)
        if not self.registry.onPresence(person, nickname, alive) and self.findPerson(person):
            self.findPerson(person).onExit(False)
            self.dropPerson(person)

    #            self.onExit(person)
    #        else:
    #            self.onEnter(conn, person, nickname)

    def revive(self):
        self.health = logic.getSystemVitality(self.target)
        [person.revive(logic.getVitality(person.name.getStripped())) for name, person in self.defenders.items()]
        self.police_notify_sent = False
        self.stat_cooldown = None

    def __str__(self):
        return u"Conference(target = %s, name = %s, health = %s, defenders = [%s], offenders = [%s])" % (
            self.target,
            self.name,
            self.health,
            ", ".join("(%s: %s)" % (k, v) for k, v in self.defenders.iteritems()),
            ", ".join("(%s: %s)" % (k, v) for k, v in self.offenders.iteritems()),
        )

    def newOffender(self, p):
        if p not in self.offenders:
            if logic.policeNotifyOnAttack(p):
                self.sendPoliceNotify(self.target)
            self.offenders[p] = Person(p, cooldown.getVitality(p))

    def newDefender(self, p):
        if p not in self.defenders:
            self.defenders[p] = Person(p, cooldown.getVitality(p))

    def idle(self, conn):
        while not self.print_queue.empty():
            res = self.print_queue.get()
            logging.info(u"receive result: %s", unicode(res))
            #            if timeout <= time.time():
            utils.sendConf(conn, self.name, res[:MAX_RESULT])
            if self.cmd_request_sent:
                utils.sendConf(
                    conn, self.name, u"Time left: %d sec. Type command." % (int(self.defeated_timeout - time.time()))
                )
                self.cmd_request_sent = None
        #           else:
        #                self.saved_message = (timeout, res)
        #                if self.defeated_timeout:
        #                    utils.sendConf(conn, self.name, u"Time left: %d sec" % (int(self.defeated_timeout - time.time())))
        if self.defeated():
            #            if self.saved_message and self.saved_message[0] <= time.time():
            #                utils.sendConf(conn, self.name, self.saved_message[1])
            #                self.saved_message = None
            if not self.defeated_commands:
                background.getUrlBackground(
                    "hack_done.php?",
                    {"hackers": ",".join(x.getNode() for x in self.offenders.keys()), "target": self.target},
                )
                rewards, score = logic.getRewardAndScore(self.target, time.time() - self.start_time)
                self.defeated_timeout = time.time() + score
                self.defeated_commands = rewards
                self.reward_person = None
                self.reward_timeout = None
                self.cmd_request_sent = None
                self.kickDefenders(conn)
                utils.sendConf(conn, self.name, u"Hacking done. Time left: %d sec. Type command." % (score))
                logging.info(u"%s Hacking done. Time left: %d sec. Type command.", self.target, score)
            else:
                if time.time() > self.defeated_timeout:
                    utils.sendConf(
                        conn,
                        self.name,
                        u"Hacking finished. Connection terminated.",
                        lambda sess, s: utils.leaveConf(conn, self.name),
                    )
                    logging.info(u"%s Finish", self.target)
                    return True
                if self.reward_timeout and time.time() > self.reward_timeout and not self.cmd_request_sent:
                    self.cmd_request_sent = True
                    background.getUrlBackground(
                        "hack_cmd.php?",
                        {"target": self.target, "cmd": self.reward_cmd, "args": " ".join(self.reward_args)},
                        self,
                    )

        if not self.offenders:
            self.revive()
            self.next_question = None
            self.start_time = None
        for l in [self.defenders, self.offenders]:
            [p.idle(conn, self) for p in l.values()]

        self.kickDeads(conn)

        if len(self.offenders) == 0 and len(self.defenders) == 0:
            return True

        if not self.defeated():
            currentTime = time.time()
            if not self.next_question:
                if self.offenders:
                    self.start_time = currentTime
                    self.next_question = currentTime + random.randint(1, config.nextQuestionMaxTimeout)
            else:
                if currentTime > self.next_question:
                    if self.question and self.offenders:
                        person = random.choice(self.offenders.values())
                        person.damage(
                            conn,
                            Person(config.nickname, 0),
                            logic.getSystemDamage(person, self.target, self.question),
                            self,
                        )
                        if logic.policeNotifyOnDamage(person.name):
                            self.sendPoliceNotify(self.target)
                    self.question = self.nextQuestion()
                    logging.info("%s: new question: %s", self.target, self.question.text)
                    self.next_question = currentTime + self.question.timeout
                    utils.sendConf(conn, self.name, self.question.text)
            return False

    def nextQuestion(self):
        return random.choice(self.questions)

    def defeated(self):
        return self.health <= 0

    def kickDefenders(self, conn):
        for jid, d in self.defenders.iteritems():
            d.revive(0)
        self.kickDeads(conn)

    def kickDeads(self, conn):
        toKick = []
        for l in [self.offenders, self.defenders]:
            toDelete = []
            for name, person in [x for x in l.iteritems() if x[1].isDead()]:
                toKick.append(self.registry.getNick(person.name))
                person.onExit(True)
                toDelete.append(name)
                if logic.policeNotifyOnKill(name):
                    self.sendPoliceNotify(self.target)
            for x in toDelete:
                del l[x]
        utils.sendKick(conn, self.name, toKick, u"Terminated!")

    def findPerson(self, person):
        for l in [self.offenders, self.defenders]:
            if person in l:
                return l[person]
        return None

    def dropPerson(self, person):
        for l in [self.offenders, self.defenders]:
            if person in l:
                del l[person]
                return

    def findRandomDefender(self, person, me):
        l = []
        exclude = unicode(me.name) if me else ""
        for n, v in self.defenders.iteritems():
            name = unicode(v.name)
            if name[: len(person)] == person and name[: len(exclude)] != exclude:
                l.append(v)
        return random.choice(l) if len(l) > 0 else None

    def findRandomOffender(self, person, me):
        l = []
        exclude = unicode(me.name) if me else ""
        for n, v in self.offenders.iteritems():
            name = unicode(v.name)
            if name[: len(person)] == person and name[: len(exclude)] != exclude:
                l.append(v)
        return random.choice(l) if len(l) > 0 else None

    def onMessage(self, conn, msg):
        res = msg.getFrom().getResource()
        if not res:
            return
        if msg.getType() != "groupchat" or not msg.getBody():
            return
        person = self.registry[res]
        if not self.findPerson(person):
            return
        logging.info(u"%s message from %s: %s", self.target, person, msg.getBody())
        if not self.defeated_commands and self.question and utils.sEq(msg.getBody(), self.question.answer):
            if person in self.offenders:
                damage = logic.getDamage(person, self.target, self.question)
                self.health -= damage
                if not self.defeated():
                    utils.answerConf(conn, msg, u"System damaged: %d, left: %d" % (damage, self.health))
                    logging.info(u"%s System damaged: %d, left: %d", self.target, damage, self.health)
                else:
                    cooldown.systemBroken(self.target)
            else:
                return
            self.question = None
            self.next_question = time.time() + random.randint(1, config.nextQuestionMaxTimeout)
        else:
            if not msg.getBody():
                return
            parts = [utils.normalize(x) for x in msg.getBody().strip().split(" ")]
            if parts:
                if self.defeated_commands and parts[0] in logic.availableRewards():
                    if parts[0] in self.defeated_commands:
                        if not self.reward_person:
                            self.rewardCommand(conn, person, parts[0], parts[1:])
                    else:
                        utils.answerConf(
                            conn,
                            msg,
                            u"Command %s is unsupported by target. Time left: %d"
                            % (parts[0], int(self.defeated_timeout - time.time())),
                        )
                else:
                    {"stat": self.printStats, "attack": self.scheduleAttack, "defend": self.doDefend}.get(
                        parts[0], lambda x, y, z: None
                    )(conn, person, parts[1:])

    def printStats(self, conn, person, args):
        now = time.time()
        if self.stat_cooldown == None or now > self.stat_cooldown:
            userlist = []
            for d in self.defenders.itervalues():
                userlist.append("defender\t%s\t%s" % (d.name, d.health))
            for o in self.offenders.itervalues():
                userlist.append("offender\t%s\t%s" % (o.name, o.health))
            msg = u"Conference info:\ntarget\t%s\nhealth\t%s\n\n%s" % (self.target, self.health, "\n".join(userlist))
            utils.sendConf(conn, self.name, unicode(msg))
            self.stat_cooldown = now + config.statCommandCooldown

    def scheduleAttack(self, conn, person, args):
        attackPerson = self.findPerson(person)
        if not attackPerson or not attackPerson.canAttack():
            return
        if len(args) < 2:
            return
        try:
            code, target = args[0], args[1]
            if len(code) == config.codeLength and int(code) >= 0:
                if person in self.offenders:
                    targetPerson = self.findRandomDefender(target, attackPerson)
                    if not targetPerson:
                        targetPerson = self.findRandomOffender(target, attackPerson)
                elif person in self.defenders:
                    targetPerson = self.findRandomOffender(target, attackPerson)
                else:
                    return
                if targetPerson:
                    targetPerson.scheduleAttack(attackPerson, code, person in self.defenders)
        except:
            logging.exception("e")

    def doDefend(self, conn, person, args):
        defenderPerson = self.findPerson(person)
        if not defenderPerson:
            return
        if len(args) < 1:
            return
        try:
            code = args[0]
            if len(args) == 2:
                target = args[1]
                if person in self.offenders:
                    targetPerson = self.findRandomDefender(target, "")
                    if not targetPerson:
                        targetPerson = self.findRandomOffender(target, "")
                elif person in self.defenders:
                    targetPerson = self.findRandomOffender(target, "")
                    if not targetPerson:
                        targetPerson = self.findRandomDefender(target, "")
                else:
                    return
            else:
                targetPerson = defenderPerson
            targetPerson.doDefend(code)
        except:
            logging.exception("e")

    def rewardCommand(self, conn, person, cmd, args):
        rewardPerson = self.findPerson(person)
        if not rewardPerson:
            return
        self.reward_person = rewardPerson
        self.reward_timeout = time.time() + logic.getCommandTime(cmd)
        self.reward_cmd = cmd
        self.reward_args = args

    def backgroundDone(self, res):
        res = res.decode("utf-8")
        self.print_queue.put((res))
        if self.reward_person and time.time() > self.reward_timeout:
            self.reward_person = None
            self.reward_timeout = None
Esempio n. 2
0
class Conf(object):
    __slots__ = ["target", "name", "health", "next_question", "defenders", "offenders", "question", "start_time", "registry", "cooldowns", "questions"]
    def __init__(self, target, name = None):
        self.target = target
        self.name = name if name else utils.randStr()
        self.health = logic.getSystemVitality(self.target)
        self.next_question = time.time() + 5
        self.start_time = self.next_question

        self.defenders = {}
        self.offenders = {}

        self.cooldowns = {}

        self.questions = logic.getQuestions(self.target)
        self.question = None
        self.registry = Registry()

#     def onExit(self, person):
#         self.cooldowns[person] = time.time() + logic.getCooldownOnExit(person, self.target)

#     def onEnter(self, conn, person, nickname):
#         if self.cooldowns.get(person, 0) > time.time():
#            utils.sendKick(conn, self.name, [nickname], u"Отдохни!")

    @utils.protect
    def onPresence(self, conn, person, nickname, alive):
        if not self.registry.onPresence(person, nickname, alive) and self.findPerson(person):
            self.findPerson(person).onExit(False)
#            self.onExit(person)
#        else:
#            self.onEnter(conn, person, nickname)

    def revive(self):
        self.health = logic.getSystemVitality(self.target)
        [person.revive(logic.getVitalityDefend(name, self.target)) for name, person in self.defenders.items()]

    def __str__(self):
        return unicode(u"Conference(target = %s, name = %s, health = %s, defenders = [%s], offenders = [%s]" % (self.target, self.name, self.health, ", ".join("(%s: %s)" % (k, v) for k, v in self.defenders.iteritems()), ", ".join("(%s: %s)" % (k, v) for k, v in self.offenders.iteritems()))).encode("utf-8")

    def newOffender(self, p):
        if p not in self.offenders:
            self.offenders[p] = Person(p, logic.getVitalityOffend(p, self.target))

    def newDefender(self, p):
        if p not in self.defenders:
            self.defenders[p] = Person(p, logic.getVitalityDefend(p, self.target))

    def idle(self, conn):
        if self.allDone():
            msg = u"Конец!"
            if self.defeated():
                msg = logic.getReward(self.target, time.time() - self.start_time)
                background.getUrlBackground("hack_done.php?", {"hackers": ",".join(x.getNode() for x in self.offenders.keys()), "target": self.target})

            utils.sendConf(conn, self.name, msg, lambda sess, s: utils.leaveConf(conn, self.name))
            return True

        if not self.offenders:
            self.revive()               

        for l in [self.defenders, self.offenders]:
            [p.idle(conn, self.name) for p in l.values()]

        self.kickDeads(conn)

        currentTime = time.time()
        if currentTime > self.next_question:
            self.question = self.nextQuestion()
            self.next_question = currentTime + self.question.timeout
            #utils.sendConf(conn, self.name, u"%s (время: %d)" % (self.question.text, self.question.timeout))
            utils.sendConf(conn, self.name, self.question.text)
        return False

    def nextQuestion(self):
        return random.choice(self.questions)

    def allDone(self):
        return self.defeated()

    def defeated(self):
        return self.health <= 0

    def kickDeads(self, conn):
        toKick = []
        for l in [self.offenders, self.defenders]:
            toDelete = []
            for name, person in [x for x in l.iteritems() if x[1].isDead()]:
                toKick.append(self.registry.getNick(person.name))
                person.onExit(True)
                toDelete.append(name)
            for x in toDelete:
                del l[x]
        utils.sendKick(conn, self.name, toKick, u"Готов")
                
    def findPerson(self, person):
        for l in [self.offenders, self.defenders]:
            if person in l:
                return l[person]
        return None

    def onMessage(self, conn, msg):
        person = self.registry[msg.getFrom().getResource()]
        if not self.findPerson(person):
            return
        if self.question and utils.sEq(msg.getBody(), self.question.answer):            
            if person in self.offenders:
                damage = logic.getDamage(person, self.target)
                self.health -= damage
                if not self.defeated():
                    utils.answerConf(conn, msg, u"Нанесено урона: %d, осталось: %d" % (damage, self.health))
            elif person in self.defenders:
                for p in self.offenders.itervalues():
                    p.damage(conn, self.findPerson(person), logic.getDefenderDamage(person, self.target), self.name)
            else:
                return
            
            self.kickDeads(conn)

            self.question = None
            self.next_question = time.time() + 1
        else:
            parts = [utils.normalize(x) for x in msg.getBody().strip().split(" ")]
            if parts:
                {"stat": self.printStats, "attack": self.scheduleAttack, "defend": self.doDefend}.get(parts[0], lambda x, y, z: None)(conn, person, parts[1:])
    
    def printStats(self, conn, person, args):
        utils.sendConf(conn, self.name, str(self))

    def scheduleAttack(self, conn, person, args):
        attackPerson = self.findPerson(person)
        if not attackPerson or not attackPerson.canAttack():
            return
        try:
            code, target = args[0], args[1]
            if len(code) == 4 and int(code) >= 0:
                targetPerson = self.findPerson(self.registry[target])
                if targetPerson:
                    targetPerson.scheduleAttack(attackPerson, code, person in self.defenders)
        except:
            print traceback.format_exc()

    def doDefend(self, conn, person, args):
        defenderPerson = self.findPerson(person)
        if not defenderPerson:
            return
        try:
            code = args[0]
            if len(args) == 2:
                targetPerson = self.findPerson(self.registry[args[1]])
            else:
                targetPerson = defenderPerson
            targetPerson.doDefend(code)
        except:
            print traceback.format_exc()
Esempio n. 3
0
class Conf(object):
    __slots__ = [
        "target", "name", "health", "next_question", "defenders", "offenders",
        "question", "start_time", "registry", "cooldowns", "questions",
        "print_queue", "defeated_commands", "reward_person", "reward_timeout",
        "defeated_timeout", "cmd_request_sent", "reward_cmd", "reward_args",
        "police_notify_sent", "stat_cooldown"
    ]

    def __init__(self, target, name=None):
        self.target = target
        self.name = name if name else utils.randStr()
        self.health = logic.getSystemVitality(self.target)
        self.next_question = None
        self.start_time = None
        self.defenders = {}
        self.offenders = {}
        #        self.cooldowns = {}
        self.questions = logic.getQuestions(self.target)
        self.question = None
        self.registry = Registry()
        self.print_queue = Queue()
        self.defeated_commands = None
        self.defeated_timeout = None
        self.reward_person = None
        self.reward_timeout = None
        self.reward_cmd = None
        self.reward_args = None
        #        self.saved_message = None
        self.cmd_request_sent = None
        self.police_notify_sent = False
        self.stat_cooldown = None

    def sendPoliceNotify(self, target):
        if not self.police_notify_sent:
            msg = u"From: %s\nTo: %s\nContent-type: text/plain;charset=utf-8\nSubject: WARNING! Target is under attack\n\nTarget: %s\nAttack time: %s" % (
                config.fromEmail, config.policeEmail, target, time.ctime())
            msg = unicode(msg).encode('utf-8')
            s = smtplib.SMTP()
            s.connect(config.mailHost, config.mailPort)
            res = s.sendmail(config.fromEmail, config.policeEmail, msg)
            logging.info("police notify sent %s", res)
            self.police_notify_sent = True

#     def onExit(self, person):
#         self.cooldowns[person] = time.time() + logic.getCooldownOnExit(person, self.target)

#     def onEnter(self, conn, person, nickname):
#         if self.cooldowns.get(person, 0) > time.time():
#            utils.sendKick(conn, self.name, [nickname], u"Отдохни!")

    @utils.protect
    def onPresence(self, conn, person, nickname, alive):
        if alive:
            logging.info(u"%s comes to %s", person, self.target)
        if not self.registry.onPresence(person, nickname,
                                        alive) and self.findPerson(person):
            self.findPerson(person).onExit(False)
            self.dropPerson(person)
#            self.onExit(person)
#        else:
#            self.onEnter(conn, person, nickname)

    def revive(self):
        self.health = logic.getSystemVitality(self.target)
        [
            person.revive(logic.getVitality(person.name.getStripped()))
            for name, person in self.defenders.items()
        ]
        self.police_notify_sent = False
        self.stat_cooldown = None

    def __str__(self):
        return u"Conference(target = %s, name = %s, health = %s, defenders = [%s], offenders = [%s])" % (
            self.target, self.name, self.health, ", ".join(
                "(%s: %s)" % (k, v)
                for k, v in self.defenders.iteritems()), ", ".join(
                    "(%s: %s)" % (k, v)
                    for k, v in self.offenders.iteritems()))

    def newOffender(self, p):
        if p not in self.offenders:
            if logic.policeNotifyOnAttack(p):
                self.sendPoliceNotify(self.target)
            self.offenders[p] = Person(p, cooldown.getVitality(p))

    def newDefender(self, p):
        if p not in self.defenders:
            self.defenders[p] = Person(p, cooldown.getVitality(p))

    def idle(self, conn):
        while not self.print_queue.empty():
            res = self.print_queue.get()
            logging.info(u"receive result: %s", unicode(res))
            #            if timeout <= time.time():
            utils.sendConf(conn, self.name, res[:MAX_RESULT])
            if self.cmd_request_sent:
                utils.sendConf(
                    conn, self.name, u"Time left: %d sec. Type command." %
                    (int(self.defeated_timeout - time.time())))
                self.cmd_request_sent = None
#           else:


#                self.saved_message = (timeout, res)
#                if self.defeated_timeout:
#                    utils.sendConf(conn, self.name, u"Time left: %d sec" % (int(self.defeated_timeout - time.time())))
        if self.defeated():
            #            if self.saved_message and self.saved_message[0] <= time.time():
            #                utils.sendConf(conn, self.name, self.saved_message[1])
            #                self.saved_message = None
            if not self.defeated_commands:
                background.getUrlBackground(
                    "hack_done.php?", {
                        "hackers":
                        ",".join(x.getNode() for x in self.offenders.keys()),
                        "target":
                        self.target
                    })
                rewards, score = logic.getRewardAndScore(
                    self.target,
                    time.time() - self.start_time)
                self.defeated_timeout = time.time() + score
                self.defeated_commands = rewards
                self.reward_person = None
                self.reward_timeout = None
                self.cmd_request_sent = None
                self.kickDefenders(conn)
                utils.sendConf(
                    conn, self.name,
                    u"Hacking done. Time left: %d sec. Type command." %
                    (score))
                logging.info(
                    u"%s Hacking done. Time left: %d sec. Type command.",
                    self.target, score)
            else:
                if time.time() > self.defeated_timeout:
                    utils.sendConf(
                        conn, self.name,
                        u"Hacking finished. Connection terminated.",
                        lambda sess, s: utils.leaveConf(conn, self.name))
                    logging.info(u"%s Finish", self.target)
                    return True
                if self.reward_timeout and time.time(
                ) > self.reward_timeout and not self.cmd_request_sent:
                    self.cmd_request_sent = True
                    background.getUrlBackground(
                        "hack_cmd.php?", {
                            "target": self.target,
                            "cmd": self.reward_cmd,
                            "args": " ".join(self.reward_args)
                        }, self)

        if not self.offenders:
            self.revive()
            self.next_question = None
            self.start_time = None
        for l in [self.defenders, self.offenders]:
            [p.idle(conn, self) for p in l.values()]

        self.kickDeads(conn)

        if len(self.offenders) == 0 and len(self.defenders) == 0:
            return True

        if not self.defeated():
            currentTime = time.time()
            if not self.next_question:
                if self.offenders:
                    self.start_time = currentTime
                    self.next_question = currentTime + random.randint(
                        1, config.nextQuestionMaxTimeout)
            else:
                if currentTime > self.next_question:
                    if self.question and self.offenders:
                        person = random.choice(self.offenders.values())
                        person.damage(
                            conn, Person(config.nickname, 0),
                            logic.getSystemDamage(person, self.target,
                                                  self.question), self)
                        if logic.policeNotifyOnDamage(person.name):
                            self.sendPoliceNotify(self.target)
                    self.question = self.nextQuestion()
                    logging.info('%s: new question: %s', self.target,
                                 self.question.text)
                    self.next_question = currentTime + self.question.timeout
                    utils.sendConf(conn, self.name, self.question.text)
            return False

    def nextQuestion(self):
        return random.choice(self.questions)

    def defeated(self):
        return self.health <= 0

    def kickDefenders(self, conn):
        for jid, d in self.defenders.iteritems():
            d.revive(0)
        self.kickDeads(conn)

    def kickDeads(self, conn):
        toKick = []
        for l in [self.offenders, self.defenders]:
            toDelete = []
            for name, person in [x for x in l.iteritems() if x[1].isDead()]:
                toKick.append(self.registry.getNick(person.name))
                person.onExit(True)
                toDelete.append(name)
                if logic.policeNotifyOnKill(name):
                    self.sendPoliceNotify(self.target)
            for x in toDelete:
                del l[x]
        utils.sendKick(conn, self.name, toKick, u"Terminated!")

    def findPerson(self, person):
        for l in [self.offenders, self.defenders]:
            if person in l:
                return l[person]
        return None

    def dropPerson(self, person):
        for l in [self.offenders, self.defenders]:
            if person in l:
                del l[person]
                return

    def findRandomDefender(self, person, me):
        l = []
        exclude = unicode(me.name) if me else ''
        for n, v in self.defenders.iteritems():
            name = unicode(v.name)
            if name[:len(person)] == person and name[:len(exclude)] != exclude:
                l.append(v)
        return random.choice(l) if len(l) > 0 else None

    def findRandomOffender(self, person, me):
        l = []
        exclude = unicode(me.name) if me else ''
        for n, v in self.offenders.iteritems():
            name = unicode(v.name)
            if name[:len(person)] == person and name[:len(exclude)] != exclude:
                l.append(v)
        return random.choice(l) if len(l) > 0 else None

    def onMessage(self, conn, msg):
        res = msg.getFrom().getResource()
        if not res:
            return
        if msg.getType() != 'groupchat' or not msg.getBody():
            return
        person = self.registry[res]
        if not self.findPerson(person):
            return
        logging.info(u"%s message from %s: %s", self.target, person,
                     msg.getBody())
        if not self.defeated_commands and self.question and utils.sEq(
                msg.getBody(), self.question.answer):
            if person in self.offenders:
                damage = logic.getDamage(person, self.target, self.question)
                self.health -= damage
                if not self.defeated():
                    utils.answerConf(
                        conn, msg, u"System damaged: %d, left: %d" %
                        (damage, self.health))
                    logging.info(u"%s System damaged: %d, left: %d",
                                 self.target, damage, self.health)
                else:
                    cooldown.systemBroken(self.target)
            else:
                return
            self.question = None
            self.next_question = time.time() + random.randint(
                1, config.nextQuestionMaxTimeout)
        else:
            if not msg.getBody(): return
            parts = [
                utils.normalize(x) for x in msg.getBody().strip().split(" ")
            ]
            if parts:
                if self.defeated_commands and parts[
                        0] in logic.availableRewards():
                    if parts[0] in self.defeated_commands:
                        if not self.reward_person:
                            self.rewardCommand(conn, person, parts[0],
                                               parts[1:])
                    else:
                        utils.answerConf(
                            conn, msg,
                            u"Command %s is unsupported by target. Time left: %d"
                            % (parts[0],
                               int(self.defeated_timeout - time.time())))
                else:
                    {
                        "stat": self.printStats,
                        "attack": self.scheduleAttack,
                        "defend": self.doDefend
                    }.get(parts[0], lambda x, y, z: None)(conn, person,
                                                          parts[1:])

    def printStats(self, conn, person, args):
        now = time.time()
        if self.stat_cooldown == None or now > self.stat_cooldown:
            userlist = []
            for d in self.defenders.itervalues():
                userlist.append("defender\t%s\t%s" % (d.name, d.health))
            for o in self.offenders.itervalues():
                userlist.append("offender\t%s\t%s" % (o.name, o.health))
            msg = u"Conference info:\ntarget\t%s\nhealth\t%s\n\n%s" % (
                self.target, self.health, "\n".join(userlist))
            utils.sendConf(conn, self.name, unicode(msg))
            self.stat_cooldown = now + config.statCommandCooldown

    def scheduleAttack(self, conn, person, args):
        attackPerson = self.findPerson(person)
        if not attackPerson or not attackPerson.canAttack():
            return
        if len(args) < 2: return
        try:
            code, target = args[0], args[1]
            if len(code) == config.codeLength and int(code) >= 0:
                if person in self.offenders:
                    targetPerson = self.findRandomDefender(
                        target, attackPerson)
                    if not targetPerson:
                        targetPerson = self.findRandomOffender(
                            target, attackPerson)
                elif person in self.defenders:
                    targetPerson = self.findRandomOffender(
                        target, attackPerson)
                else:
                    return
                if targetPerson:
                    targetPerson.scheduleAttack(attackPerson, code, person
                                                in self.defenders)
        except:
            logging.exception('e')

    def doDefend(self, conn, person, args):
        defenderPerson = self.findPerson(person)
        if not defenderPerson:
            return
        if len(args) < 1: return
        try:
            code = args[0]
            if len(args) == 2:
                target = args[1]
                if person in self.offenders:
                    targetPerson = self.findRandomDefender(target, '')
                    if not targetPerson:
                        targetPerson = self.findRandomOffender(target, '')
                elif person in self.defenders:
                    targetPerson = self.findRandomOffender(target, '')
                    if not targetPerson:
                        targetPerson = self.findRandomDefender(target, '')
                else:
                    return
            else:
                targetPerson = defenderPerson
            targetPerson.doDefend(code)
        except:
            logging.exception('e')

    def rewardCommand(self, conn, person, cmd, args):
        rewardPerson = self.findPerson(person)
        if not rewardPerson:
            return
        self.reward_person = rewardPerson
        self.reward_timeout = time.time() + logic.getCommandTime(cmd)
        self.reward_cmd = cmd
        self.reward_args = args

    def backgroundDone(self, res):
        res = res.decode('utf-8')
        self.print_queue.put((res))
        if self.reward_person and time.time() > self.reward_timeout:
            self.reward_person = None
            self.reward_timeout = None
Esempio n. 4
0
class Conf(object):
    __slots__ = ["target", "name", "health", "next_question", "defenders", "offenders", "question", "start_time", "registry", "cooldowns",
                 "questions", "print_queue", "defeated_commands", "reward_person", "reward_timeout", "defeated_timeout", "saved_message"]
    def __init__(self, target, name = None):
        self.target = target
        self.name = name if name else utils.randStr()
        self.health = logic.getSystemVitality(self.target)
        self.next_question = None
        self.start_time = None
        self.defenders = {}
        self.offenders = {}
#        self.cooldowns = {}
        self.questions = logic.getQuestions(self.target)
        self.question = None
        self.registry = Registry()
        self.print_queue = Queue()
        self.defeated_commands = None
        self.defeated_timeout = None
        self.reward_person = None
        self.reward_timeout = None
        self.saved_message = None

#     def onExit(self, person):
#         self.cooldowns[person] = time.time() + logic.getCooldownOnExit(person, self.target)

#     def onEnter(self, conn, person, nickname):
#         if self.cooldowns.get(person, 0) > time.time():
#            utils.sendKick(conn, self.name, [nickname], u"Отдохни!")

    @utils.protect
    def onPresence(self, conn, person, nickname, alive):
        if not self.registry.onPresence(person, nickname, alive) and self.findPerson(person):
            self.findPerson(person).onExit(False)
#            self.onExit(person)
#        else:
#            self.onEnter(conn, person, nickname)

    def revive(self):
        self.health = logic.getSystemVitality(self.target)
        [person.revive(logic.getVitalityDefend(name, self.target)) for name, person in self.defenders.items()]

    def __str__(self):
        return u"Conference(target = %s, name = %s, health = %s, defenders = [%s], offenders = [%s])" % (self.target, self.name, self.health, ", ".join("(%s: %s)" % (k, v) for k, v in self.defenders.iteritems()), ", ".join("(%s: %s)" % (k, v) for k, v in self.offenders.iteritems()))

    def newOffender(self, p):
        if p not in self.offenders:
            self.offenders[p] = Person(p, cooldown.getVitality(p))

    def newDefender(self, p):
        if p not in self.defenders:
            self.defenders[p] = Person(p, cooldown.getVitality(p))

    def idle(self, conn):
        while not self.print_queue.empty():
            res, timeout = self.print_queue.get()
            print u"receive result: %s" % (res)
            if timeout <= time.time():
                utils.sendConf(conn, self.name, res)
            else:
                self.saved_message = (timeout, res)
#                if self.defeated_timeout:
#                    utils.sendConf(conn, self.name, u"Time left: %d sec" % (int(self.defeated_timeout - time.time())))
        if self.defeated():
            if self.saved_message and self.saved_message[0] <= time.time():
                utils.sendConf(conn, self.name, self.saved_message[1])
                self.saved_message = None                                           
    
            if not self.defeated_commands:
                background.getUrlBackground("hack_done.php?", {"hackers": ",".join(x.getNode() for x in self.offenders.keys()), "target": self.target})
                rewards, score = logic.getRewardAndScore(self.target, time.time() - self.start_time)
                self.defeated_timeout = time.time() + score
                self.defeated_commands = rewards
                print rewards
                self.reward_person = None
                self.reward_timeout = None
                self.kickDefenders(conn)
                utils.sendConf(conn, self.name, u"Hacking done. Time left: %d sec. Type command." % (score))
            else:
                if time.time() > self.defeated_timeout:
                    utils.sendConf(conn, self.name, u"Hacking finished. Connection terminated.", lambda sess, s: utils.leaveConf(conn, self.name))
                    return True
                if self.reward_timeout and time.time() > self.reward_timeout:
                    self.reward_person = None
                    self.reward_timeout = None
                    self.saved_message = None
                    utils.sendConf(conn, self.name, u"Time left: %d sec. Type command." % (int(self.defeated_timeout - time.time())))    
            return False

        if not self.offenders:
            self.revive()
            self.next_question = None
            self.start_time = None
        for l in [self.defenders, self.offenders]:
            [p.idle(conn, self) for p in l.values()]

        self.kickDeads(conn)

        currentTime = time.time()
        if not self.next_question:
            if self.offenders:
                self.start_time = currentTime
                self.next_question = currentTime + random.randint(1, config.nextQuestionMaxTimeout)
        else:
            if currentTime > self.next_question:
                if self.question and self.offenders:
                    person = random.choice(self.offenders.values())
                    person.damage(conn, Person(config.nickname, 0), config.systemAttack, self)
                self.question = self.nextQuestion()
                self.next_question = currentTime + self.question.timeout
                utils.sendConf(conn, self.name, self.question.text)
        return False

    def nextQuestion(self):
        return random.choice(self.questions)

    def defeated(self):
        return self.health <= 0

    def kickDefenders(self, conn):
        for jid, d in self.defenders.iteritems():
            d.revive(0)
        self.kickDeads(conn)

    def kickDeads(self, conn):
        toKick = []
        for l in [self.offenders, self.defenders]:
            toDelete = []
            for name, person in [x for x in l.iteritems() if x[1].isDead()]:
                toKick.append(self.registry.getNick(person.name))
                person.onExit(True)
                toDelete.append(name)
            for x in toDelete:
                del l[x]
        utils.sendKick(conn, self.name, toKick, u"Terminated!")
                
    def findPerson(self, person):
        for l in [self.offenders, self.defenders]:
            if person in l:
                return l[person]
        return None

    def findRandomDefender(self, person, me):
        l = []
        exclude = unicode(me.name)
        for n,v in self.defenders.iteritems():
            name = unicode(v.name)
            if name[:len(person)] == person and name[:len(exclude)] != exclude:  
                l.append(v)
        return random.choice(l) if len(l) > 0 else None

    def findRandomOffender(self, person, me):
        l = []
        exclude = unicode(me.name)
        for n,v in self.offenders.iteritems():
            name = unicode(v.name)
            if name[:len(person)] == person and name[:len(exclude)] != exclude:
                l.append(v)
        return random.choice(l) if len(l) > 0 else None

    def onMessage(self, conn, msg):
        person = self.registry[msg.getFrom().getResource()]
        if not self.findPerson(person):
            return
        print u"message from %s: %s" % (person, msg.getBody())
        if not self.defeated_commands and self.question and utils.sEq(msg.getBody(), self.question.answer):            
            if person in self.offenders:
                damage = logic.getDamage(person, self.target)
                self.health -= damage
                if not self.defeated():
                    utils.answerConf(conn, msg, u"System damaged: %d, left: %d" % (damage, self.health))
            else:
                return
            self.question = None
            self.next_question = time.time() + random.randint(1, config.nextQuestionMaxTimeout)
        else:
            if not msg.getBody(): return
            parts = [utils.normalize(x) for x in msg.getBody().strip().split(" ")]
            if parts:
                if self.defeated_commands and parts[0] in logic.availableRewards():
                    if parts[0] in self.defeated_commands:
                        print u"reward command: %s" % (parts[0])
                        if not self.reward_person:
                            self.rewardCommand(conn, person, parts[0], parts[1:])
                    else:
                        utils.answerConf(conn, msg, u"Command %s is unsupported by target. Time left: %d" % (parts[0], int(self.defeated_timeout - time.time())))
                else:
                    {"stat": self.printStats, "attack": self.scheduleAttack, "defend": self.doDefend}.get(parts[0], lambda x, y, z: None)(conn, person, parts[1:])
    
    def printStats(self, conn, person, args):
        utils.sendConf(conn, self.name, unicode(self))

    def scheduleAttack(self, conn, person, args):
        attackPerson = self.findPerson(person)
        print u"person %s attacks %s can attack %s" % (attackPerson, args, attackPerson.canAttack())
        if not attackPerson or not attackPerson.canAttack():
            return
        try:
            code, target = args[0], args[1]
            if len(code) == config.codeLength and int(code) >= 0:
                if person in self.offenders:
                    targetPerson = self.findRandomDefender(target, attackPerson)
                    if not targetPerson:
                        targetPerson = self.findRandomOffender(target, attackPerson)
                elif person in self.defenders:
                    targetPerson = self.findRandomOffender(target, attackPerson)
                else:
                    return
                if targetPerson:
                    targetPerson.scheduleAttack(attackPerson, code, person in self.defenders)
        except:
            print traceback.format_exc()

    def doDefend(self, conn, person, args):
        defenderPerson = self.findPerson(person)
        if not defenderPerson:
            return
        try:
            code = args[0]
            if len(args) == 2:
                targetPerson = self.findPerson(self.registry[args[1]])
            else:
                targetPerson = defenderPerson
            targetPerson.doDefend(code)
        except:
            print traceback.format_exc()
            
    def rewardCommand(self, conn, person, cmd, args):
        rewardPerson = self.findPerson(person)
        print u"reward command %s for %s" % (cmd, self)
        if not rewardPerson:
            return
        self.reward_person = rewardPerson
        self.reward_timeout = time.time() + logic.getCommandTime(cmd)
        print u"timeout %s" % (logic.getCommandTime(cmd))
        background.getUrlBackground("hack_cmd.php?", {"target": self.target, "cmd": cmd, "args": " ".join(args)}, self, self.reward_timeout)

    def backgroundDone(self, res, timeout):
        res = res.decode('utf-8')
        print u"background done: %s timeout %s" % (res, timeout)
        self.print_queue.put((res,timeout))