remove libircclient from shared library

* removes libircclient from libzetaglest shared library because the
editor and g3d_viewer also link against libzetaglest. Those 2 binaries
don't need libircclient support

* libircclient is now built directly into only the zetaglest binary

* moved libircclient from source/shared_lib because it's no longer part
of the shared library

* libircclient put in dir "external/" because it is an "external" or
"3rd" party library. The @Supertux project does something similar
This commit is contained in:
andy5995
2018-10-07 22:29:11 -05:00
parent 57c6cc1cdd
commit bda3154a69
118 changed files with 22 additions and 64 deletions

153
external/libircclient/doc/Makefile vendored Normal file
View File

@@ -0,0 +1,153 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Libircclient.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Libircclient.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/Libircclient"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Libircclient"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."

296
external/libircclient/doc/conf.py vendored Normal file
View File

@@ -0,0 +1,296 @@
# -*- coding: utf-8 -*-
#
# Libircclient documentation build configuration file, created by
# sphinx-quickstart on Sat Jun 15 22:37:32 2013.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.rinoh.frontend.sphinx
extensions = ['sphinx.ext.doctest']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'Libircclient'
copyright = u'2005-2016 George Yunaev, http://www.ulduzsoft.com/linux/libircclient/'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '1.9'
# The full version, including alpha/beta/rc tags.
release = '1.9'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'Libircclientdoc'
# -- Options for LaTeX output --------------------------------------------------
#latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '\setcounter{tocdepth}{4}',
#}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
#latex_documents = [
# ('index', 'Libircclient.tex', u'Libircclient Documentation',
# u'George Yunaev', 'manual'),
#]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'libircclient', u'Libircclient Documentation',
[u'George Yunaev'], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output ------------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'Libircclient', u'Libircclient Documentation',
u'George Yunaev', 'Libircclient', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# -- Options for Epub output ---------------------------------------------------
# Bibliographic Dublin Core info.
epub_title = u'Libircclient'
epub_author = u'George Yunaev'
epub_publisher = u'George Yunaev'
epub_copyright = u'2013, George Yunaev'
# The language of the text. It defaults to the language option
# or en if the language is not set.
#epub_language = ''
# The scheme of the identifier. Typical schemes are ISBN or URL.
#epub_scheme = ''
# The unique identifier of the text. This can be a ISBN number
# or the project homepage.
#epub_identifier = ''
# A unique identification for the text.
#epub_uid = ''
# A tuple containing the cover image and cover page html template filenames.
#epub_cover = ()
# HTML files that should be inserted before the pages created by sphinx.
# The format is a list of tuples containing the path and title.
#epub_pre_files = []
# HTML files shat should be inserted after the pages created by sphinx.
# The format is a list of tuples containing the path and title.
#epub_post_files = []
# A list of files that should not be packed into the epub file.
#epub_exclude_files = []
# The depth of the table of contents in toc.ncx.
#epub_tocdepth = 3
# Allow duplicate toc entries.
#epub_tocdup = True
# -- Options for Rhinotype output ---------------------------------------------------
rinoh_documents = [('index', # top-level file (index.rst)
'libircclient', # output (target.pdf)
'Libircclient Documentation', # document title
'George Yunaev')] # document author
rinoh_paper_size = 'letterpaper'

52
external/libircclient/doc/index.rst vendored Normal file
View File

@@ -0,0 +1,52 @@
.. Libircclient documentation master file, created by
sphinx-quickstart on Sat Jun 15 22:37:32 2013.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Libircclient technical documentation
""""""""""""""""""""""""""""""""""""
=====================
Introduction
=====================
.. toctree::
sources/Introduction
=====================
Integration
=====================
.. toctree::
sources/Writing_code
=====================
API Reference
=====================
.. toctree::
sources/API_reference_callbacks
sources/API_reference_functions
sources/API_reference_types
sources/API_reference_constants
=====================
Appendix
=====================
.. toctree::
sources/Appendix_FAQ
sources/Appendix_LGPL
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

190
external/libircclient/doc/make.bat vendored Normal file
View File

@@ -0,0 +1,190 @@
@ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
set I18NSPHINXOPTS=%SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. texinfo to make Texinfo files
echo. gettext to make PO message catalogs
echo. changes to make an overview over all changed/added/deprecated items
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Libircclient.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Libircclient.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)
if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
:end

View File

@@ -0,0 +1,173 @@
Callbacks
~~~~~~~~~
This section describes the callbacks supported by the library.
irc_event_callback_t
^^^^^^^^^^^^^^^^^^^^
**Prototype:**
.. c:type:: typedef void (*irc_event_callback_t) (irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count)
**Parameters:**
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *session* | The IRC session, which generated the event |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *event* | The text name of the event. Useful in case a single event handler is used to handle multiple events |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *origin* | The originator of the event. Depends on the event. |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *params* | Extra parameters, if any, for this event. The number of extra parameters depends on the event, and may be zero. |
| | Each parameter is a NULL-terminated text string. None of the params can be NULL, but the *params* pointer itself could be NULL for some events. |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *count* | The number of entries in the *params* argument supplied. |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
**Description:**
Every IRC event generates a callback. This type of callback is universal and is used by almost all IRC events. Depending on the event nature, it can have zero or more parameters.
For each type of event, the number of provided parameters is fixed, and their meaning is described in the :c:type:`irc_callbacks_t` structure.
Every event has an origin (i.e. who originated the event). In some cases the *origin* variable may be NULL, which indicates that event origin is unknown. The origin usually looks like *nick!host@ircserver*,
i.e. like *tim!home@irc.server.net*. Such origins can not be used in IRC commands, and need to be stripped (i.e. host and server part should be cut off) before using. This can be done either manually, by
calling :c:func:`irc_target_get_nick`, or automatically for all the events - by setting the :c:macro:`LIBIRC_OPTION_STRIPNICKS` option with :c:func:`irc_option_set`.
irc_event_dcc_chat_t
^^^^^^^^^^^^^^^^^^^^
**Prototype:**
.. c:type:: typedef void (*irc_event_dcc_chat_t) (irc_session_t * session, const char * nick, const char * addr, irc_dcc_t dccid)
**Parameters:**
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *session* | IRC session, which generates an event (the one returned by irc_create_session) |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *nick* | User who requested the chat |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *addr* | IP address of the person such as 189.12.34.56 |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *dccid* | Identifier associated with this request which should be passed to the :c:func:`irc_dcc_accept` / :c:func:`irc_dcc_decline` functions |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
**Description:**
This callback is called when someone requests DCC CHAT with you. DCC CHAT is the type of chat which goes directly between the clients, instead of going through the IRC server. Since the TCP connection must be
established for it to happen, typically the initiator must either have the public IP or special software on the firewall which handles the necessary port forwarding.
You must respond to the chat request either by calling :c:func:`irc_dcc_accept` to accept it, or by calling :c:func:`irc_dcc_decline` to decline it.
irc_event_dcc_send_t
^^^^^^^^^^^^^^^^^^^^
**Prototype:**
.. c:type:: typedef void (*irc_event_dcc_send_t) (irc_session_t * session, const char * nick, const char * addr, const char * filename, unsigned long size, irc_dcc_t dccid)
**Parameters:**
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *session* | The IRC session, which generates an event (the one returned by irc_create_session) |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *nick* | The user who requested the chat |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *addr* | The IP address of the person such as 189.12.34.56 |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *filename* | The name of the file the user is trying to send you |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *size* | The size of the file |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *dccid* | Identifier associated with this request which should be passed to the :c:func:`irc_dcc_accept` / :c:func:`irc_dcc_decline` functions |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
**Description:**
This callback is called when someone wants to send you a file by using DCC SEND. DCC SEND goes directly between the clients, and requires the TCP connection to be established
established for it to happen. Therefore the initiator must either have the public IP or special software on the firewall which handles the necessary port forwarding.
You must respond to the chat request either by calling :c:func:`irc_dcc_accept` to accept it, or by calling :c:func:`irc_dcc_decline` to decline it.
irc_dcc_callback_t
^^^^^^^^^^^^^^^^^^
**Prototype:**
.. c:type:: typedef void (*irc_dcc_callback_t) (irc_session_t * session, irc_dcc_t id, int status, void * ctx, const char * data, unsigned int length)
**Parameters:**
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *session* | The IRC session, which generates an event (the one returned by irc_create_session) |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *id* | The DCC session id |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *status* | The DCC connection status. 0 means there is no error, otherwise contains an error code |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *ctx* | The user-provided context |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *data* | Data received (if available), otherwise NULL |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *length* | Size of the data received if any data |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
**Description:**
This callback is called for all DCC functions when state change occurs.
For DCC CHAT, the callback is called as following:
* *status* is :c:macro:`LIBIRC_ERR_CLOSED`: connection is closed by remote peer. After returning from the callback, the DCC session is automatically destroyed
* *status* is nonzero but not :c:macro:`LIBIRC_ERR_CLOSED`: socket I/O error (connect error, accept error, recv error, send error). After returning from the callback, the DCC session is automatically destroyed
* *status* is zero and *length* is zero: the remote side accepted the chat request
* *status* is zero and *length* is nonzero: new chat message received, *data* contains the message (a null-terminated string), *length* contains the string length without null terminator
For DCC SEND, while file is being sent, the callback is called as following:
* *status* is nonzero: socket I/O error (connect error, accept error, recv error, send error). After returning from the callback, the DCC session is automatically destroyed
* *status* is zero: another data packet has been sent, *length* contains the total amount of data sent so far, *data* is NULL
For DCC RECV, while file is being sending, callback called as following:
* *status* is nonzero: socket I/O error (connect error, accept error, recv error, send error). After returning from the callback, the DCC session is automatically destroyed.
* *status* is zero, and *data* is NULL: the file has been received successfully. After returning from the callback, the DCC session is automatically destroyed.
* *status* is zero, and *data* is not NULL: new data received, *data* contains the data received, *length* contains the amount of data received.
irc_eventcode_callback_t
^^^^^^^^^^^^^^^^^^^^^^^^
**Prototype:**
.. c:type:: typedef void (*irc_eventcode_callback_t) (irc_session_t * session, unsigned int event, const char * origin, const char ** params, unsigned int count)
**Parameters:**
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *session* | The IRC session, which generates an event (the one returned by irc_create_session) |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *event* | The numeric code of the event. Useful in case a single event handler is used to handle multiple events |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *origin* | The originator of the event. Depends on the event. |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *params* | Extra parameters, if any, for this event. The number of extra parameters depends on the event, and may be zero. |
| | Each parameter is a NULL-terminated text string. None of the params can be NULL, but the *params* pointer itself could be NULL for some events. |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| *count* | The number of entries in the *params* argument supplied. |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
**Description:**
This is an advanced callback for those who want to handle events deeper. Most times the IRC server replies to your actions with numeric events.
Most of those events are error codes, and some are list-start and list-stop markers. Every code has its own set of params; for details you can either experiment, or read RFC 1459
(don't expect servers to follow it closely though).
Every event has an origin (i.e. who originated the event). In some cases the *origin* variable may be NULL, which indicates that event origin is unknown. The origin usually looks like *nick!host@ircserver*,
i.e. like *tim!home@irc.server.net*. Such origins can not be used in IRC commands, and need to be stripped (i.e. host and server part should be cut off) before using. This can be done either manually, by
calling :c:func:`irc_target_get_nick`, or automatically for all the events - by setting the :c:macro:`LIBIRC_OPTION_STRIPNICKS` option with :c:func:`irc_option_set`.

View File

@@ -0,0 +1,126 @@
Constants
~~~~~~~~~
This section describes contstants such as options and the error codes.
Errors
^^^^^^
.. c:macro:: LIBIRC_ERR_OK
(0): No error
.. c:macro:: LIBIRC_ERR_INVAL
(1): An invalid value was given for one of the arguments to a function. For example, supplying the NULL value as a channel argument of :c:func:`irc_cmd_join` produces this error.
.. c:macro:: LIBIRC_ERR_RESOLV
(2): The host name supplied for :c:func:`irc_connect` function could not be resolved into valid IP address.
.. c:macro:: LIBIRC_ERR_SOCKET
(3): The new socket could not be created or made non-blocking. Usually means that the server is out of resources, or (hopefully not) a bug in libircclient. See also :ref:`faq_err_socket`
.. c:macro:: LIBIRC_ERR_CONNECT
(4): The socket could not connect to the IRC server, or to the destination DCC part. Usually means that either the IRC server is down or its address is invalid.
For DCC the reason usually is the firewall on your or destination computer, which refuses DCC transfer.
.. c:macro:: LIBIRC_ERR_CLOSED
(5): The IRC connection was closed by the IRC server (which could mean that an IRC operator just have banned you from the server - test your client before connecting to a public server), or the DCC connection
was closed by remote peer - for example, the other side just terminates the IRC application. Usually it is not an error.
.. c:macro:: LIBIRC_ERR_NOMEM
(6): There are two possible reasons for this error. First is that memory could not be allocated for libircclient internal use, and this error is usually fatal.
Second reason is that the command buffer (which queues the commands ready to be sent to the IRC server) is full, and could not accept more commands yet.
In the last case you should just wait, and repeat the command later.
.. c:macro:: LIBIRC_ERR_ACCEPT
(7): A DCC chat/send connection from the remote peer could not be accepted. Either the connection was just terminated before it is accepted, or there is a bug in libircclient.
.. c:macro:: LIBIRC_ERR_NODCCSEND
(9): A filename supplied to :c:func:`irc_dcc_sendfile` could not be sent. Either is is not a regular file (a directory or a socket, for example), or it could not be read. See also :c:macro:`LIBIRC_ERR_OPENFILE`
.. c:macro:: LIBIRC_ERR_READ
(10): Either a DCC file could not be read (for example, was truncated during sending), or a DCC socket returns a read error, which usually means that the network connection is terminated.
.. c:macro:: LIBIRC_ERR_WRITE
(11): Either a DCC file could not be written (for example, there is no free space on disk), or a DCC socket returns a write error, which usually means that the network connection is terminated.
.. c:macro:: LIBIRC_ERR_STATE
(12): The function is called when it is not allowed to be called. For example, :c:func:`irc_cmd_join` was called before the connection to IRC server succeed, and :c:member:`event_connect` is called.
.. c:macro:: LIBIRC_ERR_TIMEOUT
(13): The DCC request is timed out. There is a timer for each DCC request, which tracks connecting, accepting and non-accepted/declined DCC requests. For every request this timer
is currently set to 60 seconds. If the DCC request was not connected, accepted or declined during this time, it will be terminated with this error.
.. c:macro:: LIBIRC_ERR_OPENFILE
(14): The file specified in :c:func:`irc_dcc_sendfile` could not be opened.
.. c:macro:: LIBIRC_ERR_TERMINATED
(15): The connection to the IRC server was terminated.
.. c:macro:: LIBIRC_ERR_NOIPV6
(16): The function which requires IPv6 support was called, but the IPv6 support was not compiled into the application
.. c:macro:: LIBIRC_ERR_SSL_NOT_SUPPORTED
(17): The SSL connection was required but the library was not compiled with SSL support
.. c:macro:: LIBIRC_ERR_SSL_INIT_FAILED
(18): The SSL library could not be initialized.
.. c:macro:: LIBIRC_ERR_CONNECT_SSL_FAILED
(19): SSL handshare failed when attempting to connect to the server. Typically this means you're trying to use SSL but attempting to connect to a non-SSL port.
.. c:macro:: LIBIRC_ERR_SSL_CERT_VERIFY_FAILED
(20): The server is using an invalid or the self-signed certificate. Use :c:macro:`LIBIRC_OPTION_SSL_NO_VERIFY` option to connect to it.
.. _api_options:
Options
^^^^^^^
.. c:macro:: LIBIRC_OPTION_DEBUG
If set, enables additional debug output which goes to STDOUT.
.. c:macro:: LIBIRC_OPTION_STRIPNICKS
If set, strips the event origins automatically. Every event has an origin (i.e. who originated the event). The origin usually looks like *nick!host@ircserver*,
i.e. like *tim!home@irc.server.net*. Such origins can not be used in IRC commands, and need to be stripped (i.e. host and server part should be cut off) before using.
This can be done either manually by calling :c:func:`irc_target_get_nick`, or automatically for all the events if this option is set.
.. c:macro:: LIBIRC_OPTION_SSL_NO_VERIFY
By default the SSL connection is authenticated by verifying that the certificate presented by the server is signed by a known trusted certificate authority.
Since those typically cost money, some IRC servers use the self-signed certificates. They provide the benefits of the SSL connection but since they are
not signed by the Certificate Authority, their authencity cannot be verified. This option, if set, disables the certificate verification - the library
will accept any certificate presented by the server.
This option must be set before the :c:macro:`irc_connect` function is called.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,365 @@
Types
~~~~~
This section describes various types defined by the library.
irc_session_t
^^^^^^^^^^^^^
.. c:type:: typedef struct irc_session_s irc_session_t
The IRC session handle created by callind :c:func:`irc_create_session`. Most of the library function calls expect this handle as a parameter. You can create as many handles as you want.
Each handle could be used to establish a single IRC connection to an IRC server as a single user.
Once the handle is not used anymore, it should be destroyed by calling :c:func:`irc_destroy_session`.
irc_dcc_session_t
^^^^^^^^^^^^^^^^^
.. c:type:: typedef struct irc_dcc_session_s irc_dcc_session_t
This structure describes a DCC session used by libircclient. Its members are internal to libircclient, and should not be used directly.
irc_dcc_t
^^^^^^^^^
.. c:type:: typedef unsigned int irc_dcc_t
This type is a DCC session identifier, used to identify the DCC sessions in callbacks and various functions.
irc_callbacks_t
^^^^^^^^^^^^^^^
.. c:type:: typedef struct irc_callbacks_t
::
typedef struct
{
irc_event_callback_t event_connect;
irc_event_callback_t event_nick;
irc_event_callback_t event_quit;
irc_event_callback_t event_join;
irc_event_callback_t event_part;
irc_event_callback_t event_mode;
irc_event_callback_t event_umode;
irc_event_callback_t event_topic;
irc_event_callback_t event_kick;
irc_event_callback_t event_channel;
irc_event_callback_t event_privmsg;
irc_event_callback_t event_notice;
irc_event_callback_t event_channel_notice;
irc_event_callback_t event_invite;
irc_event_callback_t event_ctcp_req;
irc_event_callback_t event_ctcp_rep;
irc_event_callback_t event_ctcp_action;
irc_event_callback_t event_unknown;
irc_eventcode_callback_t event_numeric;
irc_event_dcc_chat_t event_dcc_chat_req;
irc_event_dcc_send_t event_dcc_send_req;
}
Describes the event callbacks structure which is used in registering the callbacks.
All the communication with the IRC network is based on events. Generally speaking, event is anything generated by someone else in the network, or by the IRC server itself.
"Someone sends you a message", "Someone has joined the channel", "Someone has quits IRC" - all these messages are events.
Every event has its own event handler, which is called when the appropriate event is received.
You don't have to define all the event handlers; define only the handlers for the events you need to intercept, and set the remaining handler pointers to NULL.
.. c:member:: event_connect
This event is triggered when the connection to the IRC server is successfully established, and the MOTD is received. Depending on the server it may also be possible to send the commands before this event.
This event uses :c:type:`irc_event_callback_t` callback with the following values:
+-------------+------------------------------------------------------------------+
| *origin* | Unused, set to NULL |
+-------------+------------------------------------------------------------------+
| *params* | Unused, set to NULL |
+-------------+------------------------------------------------------------------+
.. c:member:: event_nick
This event is triggered when the NICK message is received. It happens when one of the users (including you) in one of the channels you are watching (have joined) changed their nick.
Changing your own nick will also generate this event. Note that the server may change your nick independently, so you must track this event.
This event uses :c:type:`irc_event_callback_t` callback with the following values:
+-------------+------------------------------------------------------------------+
| *origin* | The original nick (may be yours!) |
+-------------+------------------------------------------------------------------+
| *params* | params[0] contains a new nick. |
+-------------+------------------------------------------------------------------+
.. c:member:: event_quit
This event is triggered when the QUIT message is received. It happens when one of the users in one of the channels you are watching (have joined) disconnected from the IRC server.
This event uses :c:type:`irc_event_callback_t` callback with the following values:
+-------------+-------------------------------------------------------------------+
| *origin* | The user who disconnected |
+-------------+-------------------------------------------------------------------+
| *params* | params[0] is optional, contains the user-specified reason to quit |
+-------------+-------------------------------------------------------------------+
.. c:member:: event_join
This event is triggered upon receipt of a JOIN message. It happens when a new user joins the channel you are watching (have joined). It also happens when you joined the new channel.
Note that you may be "forced" to join the channel (and therefore receive this event) without issuing the JOIN command. A typical case is when the NickServ bot on the server is configured to auto-join you to specific channels.
This event uses :c:type:`irc_event_callback_t` callback with the following values:
+-------------+-------------------------------------------------------------------+
| *origin* | The user who joined the channel (this may be you!) |
+-------------+-------------------------------------------------------------------+
| *params* | params[0] contains the channel name |
+-------------+-------------------------------------------------------------------+
.. c:member:: event_part
This event is triggered upon receipt of a PART message. It happens when a user leaves the channel you are watching (have joined). It also happens when you leave a channel.
This event uses :c:type:`irc_event_callback_t` callback with the following values:
+-------------+-------------------------------------------------------------------+
| *origin* | The user who left the channel (this may be you!) |
+-------------+-------------------------------------------------------------------+
| *params* | params[0] contains the channel name |
| | params[1] is optional and contains the user-specified reason |
+-------------+-------------------------------------------------------------------+
.. c:member:: event_mode
This event is triggered upon receipt of a channel MODE message. It happens when someone changed the mode(s) of the channel you are watching (have joined).
This event uses :c:type:`irc_event_callback_t` callback with the following values:
+-------------+-------------------------------------------------------------------+
| *origin* | The user who performed the change |
+-------------+-------------------------------------------------------------------+
| *params* | params[0] contains the channel name |
| | params[1] contains the channel mode changes, such as "+t", "-i" |
| | params[2] optional, contains the argument for the channel mode |
| | (for example, a nick for the +o mode) |
+-------------+-------------------------------------------------------------------+
.. c:member:: event_umode
This event is triggered upon receipt of a user MODE message. It happens when your user mode is changed.
This event uses :c:type:`irc_event_callback_t` callback with the following values:
+-------------+-------------------------------------------------------------------+
| *origin* | The user who performed the change |
+-------------+-------------------------------------------------------------------+
| *params* | params[0] contains the channel name |
| | params[1] contains the user mode changes, such as "+t", "-i" |
+-------------+-------------------------------------------------------------------+
.. c:member:: event_topic
This event is triggered upon receipt of a TOPIC message. It happens when someone changed the topic on the channel you are watching (have joined).
This event uses :c:type:`irc_event_callback_t` callback with the following values:
+-------------+-------------------------------------------------------------------+
| *origin* | The user who performed the change |
+-------------+-------------------------------------------------------------------+
| *params* | params[0] contains the channel name |
| | params[1] optional, contains the new topic |
+-------------+-------------------------------------------------------------------+
.. c:member:: event_kick
This event is triggered upon receipt of a KICK message. It happens when someone (including you) kicked someone (including you) from the channel you are watching (have joined).
It is possible to kick yourself from the channel.
This event uses :c:type:`irc_event_callback_t` callback with the following values:
+-------------+-------------------------------------------------------------------+
| *origin* | The user who performed the action (may be you) |
+-------------+-------------------------------------------------------------------+
| *params* | params[0] contains the channel name |
| | params[1] optional, contains the nick of the kicked |
| | params[2] optional, contains the reason for the kick |
+-------------+-------------------------------------------------------------------+
.. c:member:: event_channel
This event is triggered upon receipt of a PRIVMSG message sent to the channel. It happens when someone (but not you) sent a message to the channel you are watching (have joined).
Your own messages do not trigger this event. However the server can still "force" you to send a message to the channel by generating this event.
This event uses :c:type:`irc_event_callback_t` callback with the following values:
+-------------+-------------------------------------------------------------------+
| *origin* | The user who sent a message |
+-------------+-------------------------------------------------------------------+
| *params* | params[0] contains the channel name |
| | params[1] optional, contains the message text |
+-------------+-------------------------------------------------------------------+
.. c:member:: event_privmsg
This event is triggered upon receipt of a PRIVMSG message sent privately to you. It happens when someone sent you a message.
This event uses :c:type:`irc_event_callback_t` callback with the following values:
+-------------+-------------------------------------------------------------------+
| *origin* | The user who sent a message |
+-------------+-------------------------------------------------------------------+
| *params* | params[0] contains your nick |
| | params[1] optional, contains the message text |
+-------------+-------------------------------------------------------------------+
.. c:member:: event_notice
This event is triggered upon receipt of a NOTICE message. This message is similar to PRIVMSG and matches the event_privmsg_.
According to RFC 1459, the only difference between NOTICE and PRIVMSG is that you should NEVER automatically reply to NOTICE messages.
Unfortunately, this rule is frequently violated by IRC servers itself - for example, NICKSERV messages require reply, and are sent as NOTICE.
This event uses :c:type:`irc_event_callback_t` callback with the following values:
+-------------+-------------------------------------------------------------------+
| *origin* | The user who sent a message |
+-------------+-------------------------------------------------------------------+
| *params* | params[0] contains the target nick name |
| | params[1] optional, contains the message text |
+-------------+-------------------------------------------------------------------+
.. c:member:: event_channel_notice
This event is triggered upon receipt of a NOTICE message. This message is similar to PRIVMSG and matches the event_channel_.
According to RFC 1459, the only difference between NOTICE and PRIVMSG is that you should NEVER automatically reply to NOTICE messages.
Unfortunately, this rule is frequently violated by IRC servers itself - for example, NICKSERV messages require reply, and are sent as NOTICE.
This event uses :c:type:`irc_event_callback_t` callback with the following values:
+-------------+-------------------------------------------------------------------+
| *origin* | The user who sent a message |
+-------------+-------------------------------------------------------------------+
| *params* | params[0] contains the channel name |
| | params[1] optional, contains the message text |
+-------------+-------------------------------------------------------------------+
.. c:member:: event_invite
This event is triggered upon receipt of an INVITE message. It happens when someone invited you to a channel which has +i (invite-only) mode.
This event uses :c:type:`irc_event_callback_t` callback with the following values:
+-------------+-------------------------------------------------------------------+
| *origin* | The user who invited you |
+-------------+-------------------------------------------------------------------+
| *params* | params[0] contains your nick |
| | params[1] optional, contains the channel name |
+-------------+-------------------------------------------------------------------+
See also: :c:func:`irc_cmd_invite`
.. c:member:: event_ctcp_req
This event is triggered upon receipt of an CTCP request. By default, the built-in CTCP request handler is used.
Mirc generates *PING*, *FINGER*, *VERSION*, *TIME* and *ACTION* messages which are automatically handled by the library if this event is not handled by your application. Those messages are replied automatically
except the ACTION message which triggers event_ctcp_action_ event.
If you need to handle more types of the message, define this event handler, and check the source code of ``libirc_event_ctcp_internal`` function to see how to write your own CTCP request handler.
Note that you must support at least CTCP PING to pass the spoof check by some IRC servers.
Also you may find useful this question in FAQ: \ref faq4
This event uses :c:type:`irc_event_callback_t` callback with the following values:
+-------------+-------------------------------------------------------------------+
| *origin* | The user who generated the message |
+-------------+-------------------------------------------------------------------+
| *params* | params[0] contains the complete CTCP message |
+-------------+-------------------------------------------------------------------+
.. c:member:: event_ctcp_rep
This event is triggered upon receipt of an CTCP response. Thus if you generate the CTCP message and the remote user responded, this event handler will be called.
This event uses :c:type:`irc_event_callback_t` callback with the following values:
+-------------+-------------------------------------------------------------------+
| *origin* | The user who generated the message |
+-------------+-------------------------------------------------------------------+
| *params* | params[0] contains the complete CTCP message |
+-------------+-------------------------------------------------------------------+
.. c:member:: event_ctcp_action
This event is triggered upon receipt of an CTCP ACTION message. It is only invoked if you did not define the event_ctcp_req_ event handler.
Such messages typically look like that in the IRC client:
::
[08:32:55] * Michael is having fun
[08:32:55] * Bobby's getting jealous
This event uses :c:type:`irc_event_callback_t` callback with the following values:
+-------------+-------------------------------------------------------------------+
| *origin* | The user who generated the message |
+-------------+-------------------------------------------------------------------+
| *params* | params[0] contains the content of ACTION message |
+-------------+-------------------------------------------------------------------+
.. c:member:: event_unknown
This event is triggered upon receipt of an unknown message which is not handled by the library.
This event uses :c:type:`irc_event_callback_t` callback with the following values:
+-------------+-------------------------------------------------------------------+
| *origin* | The user who generated the event |
+-------------+-------------------------------------------------------------------+
| *params* | Zero or more parameters provided with the event |
+-------------+-------------------------------------------------------------------+
.. c:member:: event_numeric
This event is triggered upon receipt of every numeric message from the server. The incomplete list of those responses could be found in RFC 1429. This event is necessary to handle for any meaningful client.
This event uses the dedicated irc_eventcode_callback_t_ callback. See the callback documentation.
.. c:member:: event_dcc_chat_req
This event is triggered when someone attempts to establish the DCC CHAT with you.
This event uses the dedicated :c:type:`irc_event_dcc_chat_t` callback. See the callback documentation.
.. c:member:: event_dcc_send_req
This event is triggered when someone attempts to send you the file via DCC SEND.
This event uses the dedicated :c:type:`irc_event_dcc_send_t` callback. See the callback documentation.

View File

@@ -0,0 +1,134 @@
Frequently asked questions
~~~~~~~~~~~~~~~~~~~~~~~~~~
.. _faq_err_socket:
Why do I get a LIBIRC_ERR_SOCKET error under Win32 when using a static library?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Because on Win32 you have to initialize the Winsock API before using it:
.. sourcecode:: c
WSADATA wsaData;
if ( WSAStartup ( MAKEWORD (2, 2), &wsaData) != 0 )
// report an error
// Now you can use libircclient
You have to do it ONCE in your application, and since libircclient does not know whether you already initialized it or not, it does not contain any Winsock initialization code.
What does it mean that the IRC protocol is event-based?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The IRC protocol itself is asynchronous and server-driven. For you, this means the following:
- For any IRC command, it is not possible to obtain an immediate response whether the command succeed
or not. Instead the server will send the reply in a short (or long) period of time.
- For some IRC command there is no success response at all. For example, when you send a text
message, IRC server will not send anything to confirm that the message is already sent.
- You can send several commands to the IRC server, and then receive several replies regarding every
command. The order of the replies you receive is generally undefined.
- A lot of IRC events sent to you is generated by other users, or the IRC server itself, and are
sent to you just when they are generated.
- Long lists (for example, channel lists) are also sent as events. Moreover, these events could be
separated by other events (message or notices). And it is your responsibility to separate the data
(using event codes), and use some sort of data structure that will hold it until the data is complete.
It is not possible to simply query the list of channels, and expect that its content will immediately arrive.
- You may send the request, and not receive a response in case of success (such as when you send a message).
You may send the request and it will only succeed when you receive a response (which may be after you receive
ten more unrelated events). Or you can receive a response without even sending a request, as it is the case
with JOIN - it is possible for the server to JOIN you to a specific channel implicitly.
- You should be prepared to expect the unexpected from the IRC server. For example, the server can change your
nick (seen on most servers, which use nickserv authentication. You can be “forced” to join the channel, to
say something, to leave a channel, to change your usermode and so on. Listen what IRC server tells you, and do so.
Why the irc_cmd_join function does not return an error?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
A typical example is the :c:func:`irc_cmd_join` call always returns success even when you attempt to join a password-protected
channel. Then some time later the IRC server returns an error. This is because the irc_cmd family of functions return
success when the command is sent to the IRC server. The asynchronous nature of IRC makes it impossible to obtain the
command result immediately. Please read the question above.
How to register/auth with NICKSERV?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
There is no standard way. NICKSERV, CHANSERV and so on are not specified by the RFC. They are IRC extensions which
behave exactly like the other IRC users but with more power. Typically their messages are sent via Notice events, so
you can use following algorithm to handle Nickserv registration:
.. sourcecode:: c
static void event_notice (irc_session_t * session, const char * event,
const char * origin, const char ** params, unsigned int count)
{
char buf[256];
if ( !origin )
return;
if ( strcasecmp (origin, "nickserv") )
return;
if ( strstr (params[1], "This nick is not registered") == params[1] )
{
sprintf (buf, "REGISTER %s NOMAIL", gCfg.irc_nickserv_password);
irc_cmd_msg(session, "nickserv", buf);
}
else if ( strstr (params[1], "This nickname is registered and protected") == params[1] )
{
sprintf (buf, "IDENTIFY %s", gCfg.irc_nickserv_password);
irc_cmd_msg(session, "nickserv", buf);
}
else if ( strstr (params[1], "Password accepted - you are now recognized") == params[1] )
printf ("Nickserv authentication succeed.");
}
The idea is to parse the messages sent from NICKSERV, and if theyre matched the specific patterns, react on them appropriately.
What is CTCP?
^^^^^^^^^^^^^
CTCP abbreviature is deciphered as “Client-to-Client Protocol”. It is used between the IRC clients to query the
remote client for some data, or to send some information for example, /me messages are sent via CTCP.
There is no standard list of possible CTCP requests, and different IRC clients often add their own CTCP codes.
The built-in handler reacts on TIME, VERSION, PING and FINGER CTCP queries. If you need to react on other requests,
youll have to write your own CTCP handler. See the source code of libirc_event_ctcp_internal function to get an
idea how to write it.
When I am made a chanop (+o) why do I not receive the event_umode?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Becoming a channel operator channes the **channel mode**, not user mode. Therefore you will receive :c:member:`event_mode` and not :c:member:`event_umode`
If you receive the event_umode with +o this means your user is an IRC server operator.
.. _faq_epoll:
What if my application uses epoll?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The library only directly supports the select()-based loops for historic reasons, so epoll and other polling methods are not supported directly by the library.
However but if necessart, it could be emulated by converting descriptors between select and epoll as following:
* Call irc_add_select_descriptors with an empty FD_SET
* Extract the descriptors from the fd_set arrays (remember fd_array is a bitarray, not the value array). There may be more than one descriptor in case there are DCC sessions.
* Pass those descriptors to poll/epoll using relevant events (i.e. use the EPOLLIN for the descriptors in the *in_set*)
* For those descriptors which triggered the events, fill up the relevant in_set and out_set structures (again, remember the bitmasks!) and pass them to :c:func:`irc_process_select_descriptors`
While this is cumbersome, the operations are very simple (basically bitmask operations on a small structure) and will not add any significant slowdown to your application.

View File

@@ -0,0 +1,68 @@
GNU LESSER GENERAL PUBLIC LICENSE
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Version 3, 29 June 2007
Copyright © 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, “this License” refers to version 3 of the GNU Lesser General Public License, and the “GNU GPL” refers to version 3 of the GNU General Public License.
“The Library” refers to a covered work governed by this License, other than an Application or a Combined Work as defined below.
An “Application” is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library.
A “Combined Work” is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the “Linked Version”.
The “Minimal Corresponding Source” for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version.
The “Corresponding Application Code” for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version:
a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following:
a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license document.
c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.
1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version.
e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library.

View File

@@ -0,0 +1,58 @@
=====================
Introduction
=====================
Overview
~~~~~~~~
Libircclient is a small but extremely powerful library which implements the client IRC protocol. It is designed to be small, fast, portable and compatible
with the RFC standards as well as non-standard but popular features. It is perfect for building the IRC clients and bots.
Features
~~~~~~~~
- Comprehensive C API;
- Full coverage of the IRC protocol using providing functions;
- Supports multiple simultaneous connection to different IRC servers or even to the same server;
- Supports both plain and SSL connections to the IRC servers with the optional certificate check;
- Full multi-threading support, the library is thread-safe;
- All the processing could be handled by a single thread even if multiple connections are used;
- Non-blocking, asynchronous event-based interface implemented with callbacks;
- Extra support for the socket-based applications, which use select();
- CTCP support with optional build-in reply code;
- Supports CTCP PING necessary to pass the “spoof check” implemented by most IRC servers;
- Flexible DCC support, including both DCC chat, and DCC file transfer;
- Can both initiate and react to initiated DCC;
- Can accept or decline DCC sessions asynchronously;
- Written in plain C, very small binary size (around 30K depending on platform);
- Compatible all tested IRC clients;
- Free software licensed under the LGPLv3 license;
- Supports Linux as well as any POSIX-compliant Unix, Mac OS X and Microsoft Windows;
- Supports 32/64bit architectures as well as non-x86 architectures;
- IPv6 support (optional, must be compiled in);
- OpenSSL support (optional, must be compiled in);
- Cocoa interface by Nathan Ollerenshaw;
- Comprehensive documentation, examples and the FAQ;
Known issues
~~~~~~~~~~~~
Even though possible by using multiple sessions, the library is not suitable to connect to a large number of IRC servers simultaneously. If you still want to use it, you'd have to overcome the following:
- You cannot use the main loop in :c:func:`irc_run` because it only supports one session. You would have to use :c:func:`irc_add_select_descriptors`
- You'd have to handle reconnections separately by processing the relevant :c:func:`irc_process_select_descriptors` return values
- If you wish to use poll/epoll() instead of select() you'd have to write more logic as it is not directly supported. See the :ref:`FAQ <faq_epoll>`.
- The library is not optimized to have a low per-connection memory footprint, each non-SSL connection uses at least 4K, with around 32K per connection for SSL.
Author
~~~~~~
This library is created by George Yunaev, copyright 2004-2016. Please see http://www.ulduzsoft.com/linux/libircclient
License
~~~~~~~
Libircclient is licensed under Lesser General Public License version 3 or higher. The complete license text is provided in the Appendix.

View File

@@ -0,0 +1,608 @@
=====================
Integration
=====================
Requirements
~~~~~~~~~~~~
Supported operating systems and compilers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The library has been extensively tested on Linux x86 and x86_64. It has also been tested on Solaris x86, Linux on ARM and Linux on MIPS platforms, on Mac OS X on x86 and on various versions of Microsoft Windows.
Compilation
^^^^^^^^^^^
On Linux, FreeBSD and Mac OS X the library has to be compiled and installed before use unless you use a precompiled package provided by your operating system distribution. If it is provided, you are recommended to use it as it would be updated
from the central repository when the bugs are fixed.
On Microsoft Windows the official library binaries are provided, so you do not have to build it. Unless you have experience building with Cygwin, you're advised not to build from source and use the official binary.
Required libraries
******************
The library depends only on libc (glibc-devel on Linux) and gcc, although the examples require also libstdc++ (libstdc++-devel) and g++. Minimum supported version is glibc 2.2,
although if IPv6 is requested, at least glibc 2.4 is required.
If the library is built with SSL support, the openssl development package (openssl-devel) needs to be installed.
On Microsoft Windows the Cygwin with necessary development packages must be installed (and openssl-devel as well).
Compiling
*********
The library is configured and built the standard Unix way:
::
./configure [--enable-openssl] [--enable-ipv6]
make
Installing
**********
Although no install is necessary to use the libraries, the install target is provided for convenience and could be invoked via ``sudo make install``
Linking
^^^^^^^
Link your application with either libircclient.a or libircclient.so depending on your needs. If you use the system-provided library, please link with libircclient.so.
If you have built the library with SSL support, you will need to link with OpenSSL libraries; add ``-lcrypto -lssl`` to your LDFLAGS
On Microsoft Windows please link with libircclient.lib which implicitly links with libircclient.dll
Coding
~~~~~~
Initialization
^^^^^^^^^^^^^^
Include the headers
*******************
Before using the library you need to include the library header *libircclient.h*. You may also want to include *libirc_rfcnumeric.h* which provides the RFC codes:
.. sourcecode:: c
#include "libircclient.h"
#include "libirc_rfcnumeric.h"
Create event handlers
*********************
Unlike most network protocols such as HTTP or SMTP, the IRC protocol is event-based. The events come from server asynchronously. Some events are triggered by your
action (such as joining the channel or changing your nick), some are triggered by other IRC users (such as sending you a message), and some are triggered by the IRC
server itself (such as sending operation notes or invoking NickServ services).
Libircclient helps handling those events by providing the :c:type:`event handling structure <irc_callbacks_t>`. It declares the events you can define in your application,
and when such event is received from the server, the appropriate callback will be called. The number of events you need to handle depending on the complexity of your client
and the functionality it supports.
Generally there are only two events you must handle to provide a bare minimum functionality: :c:member:`event_connect` and :c:member:`event_numeric`. However it is recommended
to create an event dump function and use it for all unused events to make sure you do not miss an important event because you expected a wrong one. See function **dump_event** in
the file examples/irctest.c
Windows-specific initialization
*******************************
If you link with the **static** library on Microsoft Windows, you need to initialize the Winsock2 library before calling the library functions. It could be done by following:
.. sourcecode:: c
WSADATA wsaData;
if ( WSAStartup ( MAKEWORD (2, 2), &wsaData) != 0 )
// report an error
However if you link with the **dynamic** library (libircclient.dll) which is default if you use the official build, this is not needed because the DLL initializes it automatically on load.
Create an IRC session
*********************
To use the library at least one :c:type:`IRC session <irc_session_t>` needs to be created. One session could be used to establish a single connection to one IRC server for one nick.
However more than one session could be created if needed.
To create a session, call the :c:func:`irc_create_session` function:
.. sourcecode:: c
// The IRC callbacks structure
irc_callbacks_t callbacks;
// Init it
memset ( &callbacks, 0, sizeof(callbacks) );
// Set up the mandatory events
callbacks.event_connect = event_connect;
callbacks.event_numeric = event_numeric;
// Set up the rest of events
// Now create the session
irc_session_t * session = irc_create_session( &callbacks );
if ( !session )
// Handle the error
This code could be repeated as many times as needed to create multiple sessions. The same callback structure could be reused for multiple sessions.
Set options
***********
Besides debugging there are two options you may need to use. The :c:macro:`LIBIRC_OPTION_STRIPNICKS` enables automatic parsing of nicknames,
and since it is hard to imagine the case when it should not be enabled, we enable it:
.. sourcecode:: c
irc_option_set( session, LIBIRC_OPTION_STRIPNICKS );
The second option you may need if you use SSL connections and plan to connect to the servers which use self-signed certificates. See the
documentation for :c:macro:`LIBIRC_OPTION_SSL_NO_VERIFY`
Connect to the server
*********************
To initiate the connection to the IRC server, call the :c:func:`irc_connect` function:
.. sourcecode:: c
// Connect to a regular IRC server
if ( irc_connect (session, "irc.example.com", 6667, 0, "mynick", "myusername", "myrealname" ) )
// Handle the error: irc_strerror() and irc_errno()
To initiate the connection to the IRC server over SSL, call the :c:func:`irc_connect` function and prefix the host name or IP address with a hash symbol:
.. sourcecode:: c
// Connect to the SSL server; #192.168.1.1 is also possible
if ( irc_connect (session, "#irc.example.com", 6669, 0, "mynick", "myusername", "myrealname" ) )
// Handle the error: irc_strerror() and irc_errno()
This function only initiates the connection, so when it successfully returns the connection is only initiated, but not established yet. Then one
of the following happens after you invoke the networking handler:
- If the connection is established, you will receive the :c:member:`event_connect` - this is why it is important to handle it
- If the connection failed, the networking handler function will return failure
Connect to the IPv6 server
**************************
To initiate the connection to the IPv6 server, call the :c:func:`irc_connect6` function:
.. sourcecode:: c
if ( irc_connect6 (session, "2001:0db8:85a3:0042:1000:8a2e:0370:7334", 6669, 0, "mynick", "myusername", "myrealname" ) )
// Handle the error: irc_strerror() and irc_errno()
The rest of the details, including the return value and the SSL are the same as with regular connect.
Start the networking loop
*************************
To let the library handle the events, there are two scenarios. You can either invoke the built-in networking loop which will handle the networking and
call your events, or you can write your own loop.
Invoking the build-in networking loop is simpler but limited. Since it loops until the connection terminates, it is not an option for a GUI application
(unless you start the loop in a separate thread which you can do). And since this loop only can handle one session, it is impossible to use it if you want
to handle multiple IRC sessions. In those cases the custom networking loop, described below, should be used.
To start the event loop call the :c:func:`irc_run` function:
.. sourcecode:: c
if ( irc_run (s) )
// Either the connection to the server could not be established or terminated. See irc_errno()
Remember that irc_run() call **will not return** until the server connection is not active anymore.
Use the custom networking loop
******************************
If you use multiple sessions or have your own socket handler, you can use the custom networking loop. In this case your application must be select()-based
(:ref:`see the FAQ <faq_epoll>` if you want to use other polling methods). And you need to run the following loop:
.. sourcecode:: c
// Make sure that all the IRC sessions are connected
if ( !irc_is_connected(session) )
// reconnect it, or abort
// Create the structures for select()
struct timeval tv;
fd_set in_set, out_set;
int maxfd = 0;
// Wait 0.25 sec for the events - you can wait longer if you want to, but the library has internal timeouts
// so it needs to be called periodically even if there are no network events
tv.tv_usec = 250000;
tv.tv_sec = 0;
// Initialize the sets
FD_ZERO (&in_set);
FD_ZERO (&out_set);
// Add your own descriptors you need to wait for, if any
...
// Add the IRC session descriptors - call irc_add_select_descriptors() for each active session
irc_add_select_descriptors( session, &in_set, &out_set, &maxfd );
// Call select()
if ( select (maxfd + 1, &in_set, &out_set, 0, &tv) < 0 )
// Error
// You may also check if any descriptor is active, but again the library needs to handle internal timeouts,
// so you need to call irc_process_select_descriptors() for each session at least once in a few seconds
...
// Call irc_process_select_descriptors() for each session with the descriptor set
if ( irc_process_select_descriptors (session, &in_set, &out_set) )
// The connection failed, or the server disconnected. Handle it.
// Do it again
Channels and users
^^^^^^^^^^^^^^^^^^
Before calling any of those functions make sure you have connected to the server.
Join and leave a channel
************************
To join the channel call the :c:func:`irc_cmd_join` function with the channel name:
.. sourcecode:: c
// Join the channel #linux
if ( irc_cmd_join( session, "#linux", 0 ) )
// most likely connection error
// Join the channel $science protected by the secret key *superpassword*
if ( irc_cmd_join( session, "$science", "superpassword" ) )
// most likely connection error
You can join as many channels as you want, although the serer may restrict the number of channels you can join simultaneously.
If the join was successful you will receive the :c:member:`event_join` event. You need to wait for this event before you can perform any channel operations (such as sending the messages). However you do NOT
have to wait for this event to issue a second JOIN command as shown in the example above.
If the join was not successful, you will receive the error via :c:member:`event_numeric`.
To leave the channel call the :c:func:`irc_cmd_part` function with the channel name:
.. sourcecode:: c
// Leave the channel #linux
if ( irc_cmd_part( session, "#linux" ) )
// most likely connection error
// Leave the channel $science
if ( irc_cmd_part( session, "$science" ) )
// most likely connection error
Send a message to a channel or to a user
****************************************
After you have joined the channel, you can send a message to the channel by using the :c:func:`irc_cmd_msg` function with the channel name:
.. sourcecode:: c
// Say "Hi!" to everyone in the channel #linux
if ( irc_cmd_msg( session, "#linux", "Hi!" ) )
// most likely connection error
Technically the protocol does not require one to join the channel to send the messages into the channel. However most servers by default set
the channel mode which prevents the users who did not join the channel from sending the message into the channel.
Same function is used to send a "private" message to another user. The "private" messages do not go through the channels, but they still go through
the IRC server (sometime multiple servers) and can be seen or even logged by the IRC network operators.
.. sourcecode:: c
// Say "Hi!" to IRC user john
if ( irc_cmd_msg( session, "john", "Hi!" ) )
// most likely connection error
If the message was sent successfully you will not receive any confirmation or event. You will only receive the error via :c:member:`event_numeric`
if the message was not sent.
Receive messages from a channel or from a user
**********************************************
You receive the channel messages by handling the :c:member:`event_channel`. Each time someone says something in the channel this event is called.
You receive the "private" messages from other users by handling the :c:member:`event_privmsg`.
Those event handlers should be created in your application and passed to the library when you `create an IRC session`_
Send an action message
**********************
"Action" messages, also called /me messages, are specially formatted CTCP messages. However the library contains a special function to send
them, :c:func:`irc_cmd_me`. Actions sent by other people are handled by the :c:member:`event_ctcp_action` event.
Same as with sending messages no confirmation is received on success.
Send a CTCP request
*******************
Other CTCP requests such as PING, VERSION etc should be sent by calling :c:func:`irc_cmd_ctcp_request`. If the CTCP response is received,
it is handled by the :c:member:`event_ctcp_rep` event.
Handling DCC chat
^^^^^^^^^^^^^^^^^
Implementing the DCC callback
*****************************
No matter whether you plan to initiate DCC chats or respond to them you must implement the :c:type:`DCC callback <irc_dcc_callback_t>`:
.. sourcecode:: c
void dcc_callback (irc_session_t * session, irc_dcc_t id, int status, void * ctx, const char * data, unsigned int length)
{
if ( status )
{
// If status is LIBIRC_ERR_CLOSED, the chat has been closed by the remote party.
// Otherwise it is an error; the CHAT either terminated or could not be established. status is the error code; see irc_strerror(status)
}
else if ( length == 0 )
{
// The remote side has accepted the chat request, send "hello" something to them
irc_dcc_text( session, id, "Hello!" );
}
else
{
// We have received the chat message from the remote party
printf ("Remote party said: %s\n", data );
}
}
This callback should be passed to either :c:func:`irc_dcc_chat` function which initiates the request, or to :c:func:`irc_dcc_accept` function
which accepts the DCC CHAT request initiated by another user.
Initiating the DCC CHAT
***********************
You can initiate the DCC chat with another user by calling :c:func:`irc_dcc_chat`:
.. sourcecode:: c
// The DCC chat session id will be returned in this variable
irc_dcc_t dccid;
// Initiate the DCC chat with the IRC user "john"
if ( irc_dcc_chat( session, 0, "john", dcc_callback, &dccid ) )
// report error
Now you can proceed with other tasks. When John accepts or declines the chat, the dcc_callback() will be called, and it will be possible
to use the :c:func:`irc_dcc_text` function to send the chat messages. The callback will also be called each time a new chat message is
received, or when the chat is finished or terminated because of network error.
Responding to DCC CHAT requests
*******************************
To respond to the DCC CHAT equests your application should implement for the :c:member:`event_dcc_chat_req` event.
The callback could be implemented as following:
.. sourcecode:: c
void callback_event_dcc_chat( irc_session_t * session, const char * nick, const char * addr, irc_dcc_t dccid )
{
// User 'nick' from the IP address 'addr' tries to initiate the DCC chat with us.
// Store this information in the application internal queue together with the dccid so the callback can return
dcc_queue.store( dccid, "CHAT from " + nick + " IP address: " + addr );
}
and registered when the IRC session is created.
If your application does not handle DCC at all you can just call the :c:func:`irc_dcc_decline` function inside the callback.
If it does, we only store this information in the callback, and return. This is because the event processing will stop
until the callback returns, so popping up the dialog asking for the user confirmation would stop further events such as
channel messages from being processed. Even if your application is automatic and doesn't pop up dialogs it is still better to
separate the chat logic from the callback logic.
Somewhere later the application would check the queue in the GUI thread, get this information, and pop up the dialog asking the user
feedback. Then if the chat request was accepted, the application would call the :c:func:`irc_dcc_accept` function, and if it was
declined, the application would call the :c:func:`irc_dcc_decline` function. Both functions will accept the *dccid* which identifies
this specific request:
.. sourcecode:: c
// Somewhere in the GUI thread
if ( !dcc_queue.empty() )
{
// Get the DCC information and show the dialog to the user
irc_dcc_t dccid = dcc_chat_queue.top().dccid;
...
// React to the user entry
if ( dialog.isAccepted() )
irc_dcc_accept( session, dccid, 0, dcc_callback );
else
irc_dcc_decline( session, dccid );
}
Send CHAT messages
******************
Once the chat session is established, you can send the chat messages using :c:func:`irc_dcc_text` function. Note that you need to pass the
dcc session id instead of nick:
.. sourcecode:: c
irc_dcc_text( session, dccid, "Hello there!" );
Handling DCC file transfer
^^^^^^^^^^^^^^^^^^^^^^^^^^
This section covers handling sending and receiving files via DCC.
Implementing the callback
*************************
No matter whether you plan to send or receive files via dcc you must implement the :c:type:`DCC callback <irc_dcc_callback_t>`.
While the same callback may be used both for sending and receiving, this is not recommended since the logic is different. Therefore
the suggested implementation would be to use different callbacks as suggested:
.. sourcecode:: c
// This callback is used when we send a file to the remote party
void callback_dcc_send_file (irc_session_t * session, irc_dcc_t id, int status, void * ctx, const char * data, unsigned int length)
{
if ( status )
{
// It is an error; the send operation was either terminated or the connection could not be established. status is the error code; see irc_strerror(status)
}
else
{
// We have sent some data to the remote party, 'length' indicates how much data was sent
printf ("Sent bytes: %d\n", length );
}
}
// This callback is used when we receive a file from the remote party
void callback_dcc_recv_file (irc_session_t * session, irc_dcc_t id, int status, void * ctx, const char * data, unsigned int length)
{
if ( status )
{
// It is an error; the send operation was either terminated or the connection could not be established. status is the error code; see irc_strerror(status)
}
else if ( data == 0 )
{
// File transfer has been finished
printf ("File has been received successfully\n" );
}
else
{
// More file content has been received. Store it in memory, write to disk or something
printf ("Received %d bytes of data\n", length );
}
}
This callback should be passed to either :c:func:`irc_dcc_sendfile` function which initiates the request, or to :c:func:`irc_dcc_accept` function
which accepts the DCC RECVFILE request initiated by another user.
Sending the file via DCC
************************
You can initiate sending the file via DCC to another user by calling :c:func:`irc_dcc_sendfile`:
.. sourcecode:: c
// The DCC session id will be returned in this variable
irc_dcc_t dccid;
// Initiate sending of file "/etc/passwd" via DCC chat to the IRC user "john"
if ( irc_dcc_sendfile( session, 0, "john", "/etc/passwd", callback_dcc_send_file, &dccid ) )
// report error
Now you can proceed with other tasks. When John accepts the request, the file will be sent and callback_dcc_send_file() will be called
each time a piece of file is sent. The callback will also be called when the file has been sent, or when sending was terminated
because of network error.
Receive a file via DCC
**********************
To receive the file via DCC a remote user must initiate the DCC request to send you a file. To receive this request your application
should implement the :c:member:`event_dcc_send_req` event. The callback could be implemented as following:
.. sourcecode:: c
void callback_event_dcc_file( irc_session_t * session, const char * nick, const char * addr, const char * filename, unsigned long size, irc_dcc_t dccid )
{
// User 'nick' from the IP address 'addr' tries to initiate the DCC chat with us.
// Store this information in the application internal queue together with the dccid so the callback can return
dcc_queue.store( dccid, "CHAT from " + nick + " IP address: " + addr + ", filename " + filename );
}
If your application does not handle DCC at all you can just call the :c:func:`irc_dcc_decline` function inside the callback.
If it does, we only store this information in the callback, and return. This is because the event processing will stop
until the callback returns, so popping up the dialog asking for the user confirmation would stop further events such as
channel messages from being processed. Even if your application is automatic and doesn't pop up dialogs it is still better to
separate the chat logic from the callback logic.
Somewhere later the application would check the queue in the GUI thread, get this information, and pop up the dialog asking the user
feedback. Then if the chat request was accepted, the application would call the :c:func:`irc_dcc_accept` function, and if it was
declined, the application would call the :c:func:`irc_dcc_decline` function. Both functions will accept the *dccid* which identifies
this specific request:
.. sourcecode:: c
// Somewhere in the GUI thread
if ( !dcc_queue.empty() )
{
// Get the DCC information and show the dialog to the user
irc_dcc_t dccid = dcc_chat_queue.top().dccid;
...
// React to the user entry
if ( dialog.isAccepted() )
irc_dcc_accept( session, dccid, 0, dcc_callback );
else
irc_dcc_decline( session, dccid );
}
Note that it is not possible to request a remote user to send you a file.
Handling colors
^^^^^^^^^^^^^^^
.. _color_stripping:
Stripping colors from the message
*********************************
If your bot reacts on the text messages, you need to strip down the colors from the text messages before processing them. Otherwise the user sending
the colored message won't get the same reaction as the user who doesn't use colors, and some users use colors by default.
Use the :c:func:`irc_color_strip_from_mirc` function to strip the ANSI colors from the text message. It does not modify the message which doesn't use colors.
Color conversion
****************
The library supports color translation, and can convert colors between the ANSI colors used by the IRC clients and their textual representation.
Colors usage is typically limited to the messages and user specified reasons. You cannot use colors as part of your nick or channel name.
Use the :c:func:`irc_color_convert_from_mirc` function to convert colors from ANSI to the library textual representation, and :c:func:`irc_color_convert_to_mirc`
to convert the library textual representation of colors into ANSI.
Do not forget to free() the returned pointer once it is not used anymore.
Miscellaneous
^^^^^^^^^^^^^
Tracking user nicks
*******************
If your application maintains some user-specific quotas, it is important to track the nick changes. Since the nick is the only identifier
available to you, each time the user changes the nick you need to update your quota database. To do so you need to intercept the :c:member:`event_nick`
event. See the examples/censor.c for details.