示例#1
0
文件: github.py 项目: nbr23/nemubot
def cmd_github(msg):
    if not len(msg.args):
        raise IMException("indicate a repository name to search")

    repos = info_repos(" ".join(msg.args))

    res = Response(channel=msg.channel, nomore="No more repository", count=" (%d more repo)")

    for repo in repos["items"]:
        homepage = ""
        if repo["homepage"] is not None:
            homepage = repo["homepage"] + " - "
        res.append_message(
            "Repository %s: %s%s Main language: %s; %d forks; %d stars; %d watchers; %d opened_issues; view it at %s"
            % (
                repo["full_name"],
                homepage,
                repo["description"],
                repo["language"],
                repo["forks"],
                repo["stargazers_count"],
                repo["watchers_count"],
                repo["open_issues_count"],
                repo["html_url"],
            )
        )

    return res
示例#2
0
def cmd_imdb(msg):
    if not len(msg.args):
        raise IMException("precise a movie/serie title!")

    title = ' '.join(msg.args)

    if re.match("^tt[0-9]{7}$", title) is not None:
        data = get_movie(imdbid=title)
    else:
        rm = re.match(r"^(.+)\s\(([0-9]{4})\)$", title)
        if rm is not None:
            data = get_movie(title=rm.group(1), year=rm.group(2))
        else:
            data = get_movie(title=title)

    res = Response(channel=msg.channel,
                   title="%s (%s)" % (data['Title'], data['Year']),
                   nomore="No more information, more at http://www.imdb.com/title/%s" % data['imdbID'])

    res.append_message("\x02rating\x0F: %s (%s votes); \x02plot\x0F: %s" %
                       (data['imdbRating'], data['imdbVotes'], data['Plot']))

    res.append_message("%s \x02from\x0F %s \x02released on\x0F %s; \x02genre:\x0F %s; \x02directed by:\x0F %s; \x02written by:\x0F %s; \x02main actors:\x0F %s"
                       % (data['Type'], data['Country'], data['Released'], data['Genre'], data['Director'], data['Writer'], data['Actors']))
    return res
示例#3
0
文件: github.py 项目: nbr23/nemubot
def cmd_github_user(msg):
    if not len(msg.args):
        raise IMException("indicate a user name to search")

    res = Response(channel=msg.channel, nomore="No more user")

    user = info_user(" ".join(msg.args))

    if "login" in user:
        if user["repos"]:
            kf = " Known for: " + ", ".join([repo["name"] for repo in user["repos"]])
        else:
            kf = ""
        if "name" in user:
            name = user["name"]
        else:
            name = user["login"]
        res.append_message(
            "User %s: %d public repositories; %d public gists; %d followers; %d following; view it at %s.%s"
            % (
                name,
                user["public_repos"],
                user["public_gists"],
                user["followers"],
                user["following"],
                user["html_url"],
                kf,
            )
        )
    else:
        raise IMException("User not found")

    return res
示例#4
0
def get_tracking_info(msg):
    if not len(msg.args):
        raise IMException("Renseignez un identifiant d'envoi.")

    res = Response(channel=msg.channel, count=" (%d suivis supplémentaires)")

    if 'tracker' in msg.kwargs:
        if msg.kwargs['tracker'] in TRACKING_HANDLERS:
            trackers = {
                msg.kwargs['tracker']: TRACKING_HANDLERS[msg.kwargs['tracker']]
            }
        else:
            raise IMException("No tracker named \x02{tracker}\x0F, please use"
                               " one of the following: \x02{trackers}\x0F"
                               .format(tracker=msg.kwargs['tracker'],
                                       trackers=', '
                                       .join(TRACKING_HANDLERS.keys())))
    else:
        trackers = TRACKING_HANDLERS

    for tracknum in msg.args:
        for name, tracker in trackers.items():
            ret = tracker(tracknum)
            if ret:
                res.append_message(ret)
                break
        if not ret:
            res.append_message("L'identifiant \x02{id}\x0F semble incorrect,"
                               " merci de vérifier son exactitude."
                               .format(id=tracknum))
    return res
示例#5
0
文件: github.py 项目: nbr23/nemubot
def cmd_github_commit(msg):
    if not len(msg.args):
        raise IMException("indicate a repository to view its commits")

    commit = None
    if re.match("^[a-fA-F0-9]+$", msg.args[0]):
        commit = msg.args[0]
        del msg.args[0]
    elif re.match("^[a-fA-F0-9]+$", msg.args[-1]):
        commit = msg.args[-1]
        del msg.args[-1]

    repo = " ".join(msg.args)

    count = " (%d more commits)" if commit is None else None
    res = Response(channel=msg.channel, nomore="No more commit", count=count)

    commits = info_commit(repo, commit)

    if commits is None:
        raise IMException("Repository or commit not found")

    for commit in commits:
        res.append_message(
            "Commit %s by %s on %s: %s"
            % (
                commit["sha"][:10],
                commit["commit"]["author"]["name"],
                commit["commit"]["author"]["date"],
                commit["commit"]["message"].replace("\n", " "),
            )
        )
    return res
示例#6
0
def get_cve_desc(msg):
    res = Response(channel=msg.channel)

    for cve_id in msg.args:
        if cve_id[:3].lower() != 'cve':
            cve_id = 'cve-' + cve_id

        res.append_message(get_cve(cve_id))

    return res
示例#7
0
文件: github.py 项目: nbr23/nemubot
def cmd_github_user_keys(msg):
    if not len(msg.args):
        raise IMException("indicate a user name to search")

    res = Response(channel=msg.channel, nomore="No more keys")

    for k in user_keys(" ".join(msg.args)):
        res.append_message(k)

    return res
示例#8
0
def cmd_srchmediawiki(msg):
    if len(msg.args) < 2:
        raise IMException("indicate a domain and a term to search")

    res = Response(channel=msg.to_response, nomore="No more results", count=" (%d more results)")

    for r in search(msg.args[0], " ".join(msg.args[1:]), **msg.kwargs):
        res.append_message("%s: %s" % r)

    return res
示例#9
0
def cmd_alert(msg):
    loc, coords, specific = treat_coord(msg)
    wth = get_json_weather(coords)

    res = Response(channel=msg.channel, nomore="No more weather alert", count=" (%d more alerts)")

    if "alerts" in wth:
        for alert in wth["alerts"]:
            res.append_message("\x03\x02%s\x03\x02 (see %s expire on %s): %s" % (alert["title"], alert["uri"], format_timestamp(int(alert["expires"]), wth["timezone"], wth["offset"]), alert["description"].replace("\n", " ")))

    return res
示例#10
0
def cmd_book(msg):
    if not len(msg.args):
        raise IMException("please give me a title to search")

    book = get_book(" ".join(msg.args))
    if book is None:
        raise IMException("unable to find book named like this")
    res = Response(channel=msg.channel)
    res.append_message("%s, written by %s: %s" % (book.getElementsByTagName("title")[0].firstChild.nodeValue,
                                                 book.getElementsByTagName("author")[0].getElementsByTagName("name")[0].firstChild.nodeValue,
                                                 web.striphtml(book.getElementsByTagName("description")[0].firstChild.nodeValue if book.getElementsByTagName("description")[0].firstChild else "")))
    return res
示例#11
0
def cmd_books(msg):
    if not len(msg.args):
        raise IMException("please give me a title to search")

    title = " ".join(msg.args)
    res = Response(channel=msg.channel,
                   title="%s" % (title),
                   count=" (%d more books)")

    for book in search_books(title):
        res.append_message("%s, writed by %s" % (book.getElementsByTagName("best_book")[0].getElementsByTagName("title")[0].firstChild.nodeValue,
                                                 book.getElementsByTagName("best_book")[0].getElementsByTagName("author")[0].getElementsByTagName("name")[0].firstChild.nodeValue))
    return res
示例#12
0
def cmd_whois(msg):
    if len(msg.args) < 1:
        raise IMException("Provide a name")

    res = Response(channel=msg.channel, count=" (%d more logins)")
    for srch in msg.args:
        l = found_login(srch)
        if l is not None:
            pic = l.get_photo()
            res.append_message("%s is %s (%s %s): %s%s" % (srch, l.cn.capitalize(), l.login, l.uid, l.get_promo(), " and looks like %s" % pic if pic is not None else ""))
        else:
            res.append_message("Unknown %s :(" % srch)
    return res
示例#13
0
def udsearch(msg):
    if not len(msg.args):
        raise IMException("Indicate a term to search")

    s = search(msg.args)

    res = Response(channel=msg.channel, nomore="No more results",
                   count=" (%d more definitions)")

    for i in s["list"]:
        res.append_message(i["definition"].replace("\n", "  "),
                           title=i["word"])

    return res
示例#14
0
def get_info_yt(msg):
    soup = BeautifulSoup(getURLContent(URL))

    res = Response(channel=msg.channel, nomore="No more upcoming CTF")

    for line in soup.body.find_all('tr'):
        n = line.find_all('td')
        if len(n) == 5:
            try:
                res.append_message("\x02%s:\x0F from %s type %s at %s. %s" %
                                   tuple([striphtml(x.text) for x in n]))
            except:
                pass
    return res
示例#15
0
def cmd_whatis(msg):
    args = ["whatis", " ".join(msg.args)]

    res = Response(channel=msg.channel)
    with subprocess.Popen(args,
                          stdout=subprocess.PIPE,
                          stderr=subprocess.PIPE) as proc:
        for line in proc.stdout.read().split(b"\n"):
            (line, n) = RGXP_s.subn(b'', line)
            res.append_message(" ".join(line.decode().split()))

    if len(res.messages) <= 0:
        res.append_message("There is no man page for %s." % msg.args[0])

    return res
示例#16
0
def cmd_news(msg):
    if not len(msg.args):
        raise IMException("Indicate the URL to visit.")

    url = " ".join(msg.args)
    links = [x for x in find_rss_links(url)]
    if len(links) == 0: links = [ url ]

    res = Response(channel=msg.channel, nomore="No more news from %s" % url)
    for n in get_last_news(links[0]):
        res.append_message("%s published %s: %s %s" % (("\x02" + web.striphtml(n.title) + "\x0F") if n.title else "An article without title",
                                                       (n.updated.strftime("on %A %d. %B %Y at %H:%M") if n.updated else "someday") if isinstance(n, AtomEntry) else n.pubDate,
                                                       web.striphtml(n.summary) if n.summary else "",
                                                       n.link if n.link else ""))
    return res
示例#17
0
def cmd_subreddit(msg):
    global LAST_SUBS
    if not len(msg.args):
        if msg.channel in LAST_SUBS and len(LAST_SUBS[msg.channel]) > 0:
            subs = [LAST_SUBS[msg.channel].pop()]
        else:
            raise IMException("Which subreddit? Need inspiration? "
                               "type !horny or !bored")
    else:
        subs = msg.args

    all_res = list()
    for osub in subs:
        sub = re.match(r"^/?(?:(\w)/)?(\w+)/?$", osub)
        if sub is not None:
            if sub.group(1) is not None and sub.group(1) != "":
                where = sub.group(1)
            else:
                where = "r"

            sbr = web.getJSON("http://www.reddit.com/%s/%s/about.json" %
                              (where, sub.group(2)))

            if sbr is None:
                raise IMException("subreddit not found")

            if "title" in sbr["data"]:
                res = Response(channel=msg.channel,
                               nomore="No more information")
                res.append_message(
                    ("[NSFW] " if sbr["data"]["over18"] else "") +
                    sbr["data"]["url"] + " " + sbr["data"]["title"] + ": " +
                    sbr["data"]["public_description" if sbr["data"]["public_description"] != "" else "description"].replace("\n", " ") +
                    " %s subscriber(s)" % sbr["data"]["subscribers"])
                if sbr["data"]["public_description"] != "":
                    res.append_message(
                        sbr["data"]["description"].replace("\n", " "))
                all_res.append(res)
            else:
                all_res.append(Response("/%s/%s doesn't exist" %
                                        (where, sub.group(2)),
                                        channel=msg.channel))
        else:
            all_res.append(Response("%s is not a valid subreddit" % osub,
                                    channel=msg.channel, nick=msg.nick))

    return all_res
示例#18
0
def cmd_man(msg):
    args = ["man"]
    num = None
    if len(msg.args) == 1:
        args.append(msg.args[0])
    elif len(msg.args) >= 2:
        try:
            num = int(msg.args[0])
            args.append("%d" % num)
            args.append(msg.args[1])
        except ValueError:
            args.append(msg.args[0])

    os.unsetenv("LANG")
    res = Response(channel=msg.channel)
    with subprocess.Popen(args,
                          stdout=subprocess.PIPE,
                          stderr=subprocess.PIPE) as proc:
        for line in proc.stdout.read().split(b"\n"):
            (line, n) = RGXP_s.subn(b'', line)
            res.append_message(line.decode())

    if len(res.messages) <= 0:
        if num is not None:
            res.append_message("There is no entry %s in section %d." %
                               (msg.args[0], num))
        else:
            res.append_message("There is no man page for %s." % msg.args[0])

    return res
示例#19
0
def cmd_spell(msg):
    if not len(msg.args):
        raise IMException("indique une orthographe approximative du mot dont tu veux vérifier l'orthographe.")

    lang = msg.kwargs["lang"] if "lang" in msg.kwargs else "fr"

    res = Response(channel=msg.channel)
    for word in msg.args:
        try:
            r = check_spell(word, lang)
        except AspellError:
            raise IMException("Je n'ai pas le dictionnaire `%s' :(" % lang)

        if r == True:
            add_score(msg.nick, "correct")
            res.append_message("l'orthographe de `%s' est correcte" % word)

        elif len(r) > 0:
            add_score(msg.nick, "bad")
            res.append_message(r, title="suggestions pour `%s'" % word)

        else:
            add_score(msg.nick, "bad")
            res.append_message("aucune suggestion pour `%s'" % word)

    return res
示例#20
0
def get_info_yt(msg):
  links = list()

  if len(msg.args) <= 0:
    global LAST_URLS
    if msg.channel in LAST_URLS and len(LAST_URLS[msg.channel]) > 0:
      links.append(LAST_URLS[msg.channel].pop())
    else:
      raise IMException("I don't have any youtube URL for now, please provide me one to get information!")
  else:
    for url in msg.args:
      links.append(url)

  data = _get_ytdl(links)
  res = Response(channel=msg.channel)
  for msg in data:
    res.append_message(msg)
  return res
示例#21
0
def cmd_translate(msg):
    if not len(msg.args):
        raise IMException("which word would you translate?")

    langFrom = msg.kwargs["from"] if "from" in msg.kwargs else "en"
    if "to" in msg.kwargs:
        langTo = msg.kwargs["to"]
    else:
        langTo = "fr" if langFrom == "en" else "en"

    if langFrom not in LANG or langTo not in LANG:
        raise IMException("sorry, I can only translate to or from: " + ", ".join(LANG))
    if langFrom != "en" and langTo != "en":
        raise IMException("sorry, I can only translate to or from english")

    res = Response(channel=msg.channel,
                   count=" (%d more meanings)",
                   nomore="No more translation")
    for t in translate(" ".join(msg.args), langFrom=langFrom, langTo=langTo):
        res.append_message(t)
    return res
示例#22
0
def cmd_tcode(msg):
    if not len(msg.args):
        raise IMException("indicate a transaction code or "
                           "a keyword to search!")

    url = ("http://www.tcodesearch.com/tcodes/search?q=%s" %
           urllib.parse.quote(msg.args[0]))

    page = web.getURLContent(url)
    soup = BeautifulSoup(page)

    res = Response(channel=msg.channel,
                   nomore="No more transaction code",
                   count=" (%d more tcodes)")


    search_res = soup.find("", {'id':'searchresults'})
    for item in search_res.find_all('dd'):
        res.append_message(item.get_text().split('\n')[1].strip())

    return res
示例#23
0
def go(msg, what):
    if not len(msg.args):
        raise IMException("de quel mot veux-tu connaître la liste des synonymes ?")

    lang = msg.kwargs["lang"] if "lang" in msg.kwargs else "fr"
    word = ' '.join(msg.args)

    try:
        best, synos, anton = lang_binding[lang](word)
    except:
        best, synos, anton = (list(), list(), list())

    if what == "synonymes":
        if len(synos) > 0 or len(best) > 0:
            res = Response(channel=msg.channel, title="Synonymes de %s" % word)
            if len(best) > 0: res.append_message(best)
            if len(synos) > 0: res.append_message(synos)
            return res
        else:
            raise IMException("Aucun synonyme de %s n'a été trouvé" % word)

    elif what == "antonymes":
        if len(anton) > 0:
            res = Response(anton, channel=msg.channel,
                            title="Antonymes de %s" % word)
            return res
        else:
            raise IMException("Aucun antonyme de %s n'a été trouvé" % word)

    else:
        raise IMException("WHAT?!")
示例#24
0
文件: github.py 项目: nbr23/nemubot
def cmd_github_issue(msg):
    if not len(msg.args):
        raise IMException("indicate a repository to view its issues")

    issue = None

    li = re.match("^#?([0-9]+)$", msg.args[0])
    ri = re.match("^#?([0-9]+)$", msg.args[-1])
    if li is not None:
        issue = li.group(1)
        del msg.args[0]
    elif ri is not None:
        issue = ri.group(1)
        del msg.args[-1]

    repo = " ".join(msg.args)

    count = " (%d more issues)" if issue is None else None
    res = Response(channel=msg.channel, nomore="No more issue", count=count)

    issues = info_issue(repo, issue)

    if issues is None:
        raise IMException("Repository not found")

    for issue in issues:
        res.append_message(
            "%s%s issue #%d: \x03\x02%s\x03\x02 opened by %s on %s: %s"
            % (
                issue["state"][0].upper(),
                issue["state"][1:],
                issue["number"],
                issue["title"],
                issue["user"]["login"],
                issue["created_at"],
                issue["body"].replace("\n", " "),
            )
        )
    return res
示例#25
0
def cmd_flight(msg):
    if not len(msg.args):
        raise IMException("please indicate a flight")

    res = Response(channel=msg.channel, nick=msg.nick,
                   nomore="No more flights", count=" (%s more flights)")

    for param in msg.args:
        for flight in virtual_radar(param):
            if 'Lat' in flight and 'Long' in flight:
                loc = None
                for location in  mapquest.geocode('{Lat},{Long}'.format(**flight)):
                    loc = location
                    break
                if loc:
                    res.append_message('\x02{0}\x0F: Position: \x02{1}\x0F, {2}'.format(flight['Call'], \
                            mapquest.where(loc), \
                            ', '.join(filter(None, flight_info(flight)))))
                    continue
            res.append_message('\x02{0}\x0F: {1}'.format(flight['Call'], \
                        ', '.join(filter(None, flight_info(flight)))))
    return res
示例#26
0
def parseanswer(msg):
    res = Response(channel=msg.channel)

    # Avoid message starting by ! which can be interpreted as command by other bots
    if msg.cmd[0] == "!":
        res.nick = msg.nick

    if context.data.index[msg.cmd].name == "strend":
        if context.data.index[msg.cmd].hasAttribute("end"):
            res.append_message("%s commencé il y a %s et se terminera dans %s." % (msg.cmd, countdown(msg.date - context.data.index[msg.cmd].getDate("start")), countdown(context.data.index[msg.cmd].getDate("end") - msg.date)))
        else:
            res.append_message("%s commencé il y a %s." % (msg.cmd, countdown(msg.date - context.data.index[msg.cmd].getDate("start"))))
    else:
        res.append_message(countdown_format(context.data.index[msg.cmd].getDate("start"), context.data.index[msg.cmd]["msg_before"], context.data.index[msg.cmd]["msg_after"]))
    return res
示例#27
0
def cmd_worldcup(msg):
    res = Response(channel=msg.channel, nomore="No more match to display", count=" (%d more matches)")

    url = None
    if len(msg.args) == 1:
        if msg.args[0] == "today" or msg.args[0] == "aujourd'hui":
            url = "matches/today?by_date=ASC"
        elif msg.args[0] == "tomorrow" or msg.args[0] == "demain":
            url = "matches/tomorrow?by_date=ASC"
        elif msg.args[0] == "all" or msg.args[0] == "tout" or msg.args[0] == "tous":
            url = "matches/"
        elif len(msg.args[0]) == 3:
            url = "matches/country?fifa_code=%s&by_date=DESC" % msg.args[0]
        elif is_int(msg.args[0]):
            url = int(msg.arg[0])
        else:
            raise IMException("unrecognized request; choose between 'today', 'tomorrow', a FIFA country code or a match identifier")

    if url is None:
        url = "matches/current?by_date=ASC"
        res.nomore = "There is no match currently"

    if isinstance(url, int):
        matches = get_match(API_URL % "matches/", url)
    else:
        matches = [m for m in get_matches(API_URL % url)]

    for match in matches:
        if len(matches) == 1:
            res.count = " (%d more actions)"
            for m in prettify(match):
                res.append_message(m)
        else:
            res.append_message(prettify(match)[0])

    return res
示例#28
0
def search(msg):
    if not len(msg.args):
        raise IMException("Indicate a term to search")

    s = do_search(msg.args)

    res = Response(channel=msg.channel, nomore="No more results",
                   count=" (%d more results)")

    res.append_message(s.redirect)
    res.append_message(s.answer)
    res.append_message(s.abstract)
    res.append_message([r for r in s.result])

    for rt in s.relatedTopics:
        res.append_message(rt)

    res.append_message(s.definition)

    return res
示例#29
0
def cmd_weather(msg):
    loc, coords, specific = treat_coord(msg)
    wth = get_json_weather(coords)

    res = Response(channel=msg.channel, nomore="No more weather information")

    if "alerts" in wth:
        alert_msgs = list()
        for alert in wth["alerts"]:
            alert_msgs.append("\x03\x02%s\x03\x02 expire on %s" % (alert["title"], format_timestamp(int(alert["expires"]), wth["timezone"], wth["offset"])))
        res.append_message("\x03\x16\x03\x02/!\\\x03\x02 Alert%s:\x03\x16 " % ("s" if len(alert_msgs) > 1 else "") + ", ".join(alert_msgs))

    if specific is not None:
        gr = re.match(r"^([0-9]*)\s*([a-zA-Z])", specific)
        if gr is None or gr.group(1) == "":
            gr1 = 1
        else:
            gr1 = int(gr.group(1))

        if gr.group(2).lower() == "h" and gr1 < len(wth["hourly"]["data"]):
            hour = wth["hourly"]["data"][gr1]
            res.append_message("\x03\x02At %sh:\x03\x02 %s" % (format_timestamp(int(hour["time"]), wth["timezone"], wth["offset"], '%H'), format_wth(hour)))

        elif gr.group(2).lower() == "d" and gr1 < len(wth["daily"]["data"]):
            day = wth["daily"]["data"][gr1]
            res.append_message("\x03\x02On %s:\x03\x02 %s" % (format_timestamp(int(day["time"]), wth["timezone"], wth["offset"], '%A'), format_forecast_daily(day)))

        else:
            res.append_message("I don't understand %s or information is not available" % specific)

    else:
        res.append_message("\x03\x02Currently:\x03\x02 " + format_wth(wth["currently"]))

        nextres = "\x03\x02Today:\x03\x02 %s " % wth["daily"]["data"][0]["summary"]
        if "minutely" in wth:
            nextres += "\x03\x02Next hour:\x03\x02 %s " % wth["minutely"]["summary"]
        nextres += "\x03\x02Next 24 hours:\x03\x02 %s \x03\x02Next week:\x03\x02 %s" % (wth["hourly"]["summary"], wth["daily"]["summary"])
        res.append_message(nextres)

        for hour in wth["hourly"]["data"][1:4]:
            res.append_message("\x03\x02At %sh:\x03\x02 %s" % (format_timestamp(int(hour["time"]), wth["timezone"], wth["offset"], '%H'),
                                                               format_wth(hour)))

        for day in wth["daily"]["data"][1:]:
            res.append_message("\x03\x02On %s:\x03\x02 %s" % (format_timestamp(int(day["time"]), wth["timezone"], wth["offset"], '%A'),
                                                              format_forecast_daily(day)))

    return res
示例#30
0
 def _help_msg(msg):
     """Parse and response to help messages"""
     from more import Response
     res = Response(channel=msg.to_response)
     if len(msg.args) >= 1:
         if msg.args[0] in self.modules:
             if hasattr(self.modules[msg.args[0]], "help_full"):
                 hlp = self.modules[msg.args[0]].help_full()
                 if isinstance(hlp, Response):
                     return hlp
                 else:
                     res.append_message(hlp)
             else:
                 res.append_message([str(h) for s,h in self.modules[msg.args[0]].__nemubot_context__.hooks], title="Available commands for module " + msg.args[0])
         elif msg.args[0][0] == "!":
             from nemubot.message.command import Command
             for h in self.treater._in_hooks(Command(msg.args[0][1:])):
                 if h.help_usage:
                     lp = ["\x03\x02%s%s\x03\x02: %s" % (msg.args[0], (" " + k if k is not None else ""), h.help_usage[k]) for k in h.help_usage]
                     jp = h.keywords.help()
                     return res.append_message(lp + ([". Moreover, you can provides some optional parameters: "] + jp if len(jp) else []), title="Usage for command %s" % msg.args[0])
                 elif h.help:
                     return res.append_message("Command %s: %s" % (msg.args[0], h.help))
                 else:
                     return res.append_message("Sorry, there is currently no help for the command %s. Feel free to make a pull request at https://github.com/nemunaire/nemubot/compare" % msg.args[0])
             res.append_message("Sorry, there is no command %s" % msg.args[0])
         else:
             res.append_message("Sorry, there is no module named %s" % msg.args[0])
     else:
         res.append_message("Pour me demander quelque chose, commencez "
                            "votre message par mon nom ; je réagis "
                            "également à certaine commandes commençant par"
                            " !.  Pour plus d'informations, envoyez le "
                            "message \"!more\".")
         res.append_message("Mon code source est libre, publié sous "
                            "licence AGPL (http://www.gnu.org/licenses/). "
                            "Vous pouvez le consulter, le dupliquer, "
                            "envoyer des rapports de bogues ou bien "
                            "contribuer au projet sur GitHub : "
                            "http://github.com/nemunaire/nemubot/")
         res.append_message(title="Pour plus de détails sur un module, "
                            "envoyez \"!help nomdumodule\". Voici la liste"
                            " de tous les modules disponibles localement",
                            message=["\x03\x02%s\x03\x02 (%s)" % (im, self.modules[im].__doc__) for im in self.modules if self.modules[im].__doc__])
     return res