mirror of
https://github.com/Tha14/toxic.git
synced 2025-06-29 21:36:46 +02:00
Compare commits
94 Commits
v0.8.0
...
new_groupc
Author | SHA1 | Date | |
---|---|---|---|
9dfa455561 | |||
372fcb0a67 | |||
c760ffc563 | |||
c6f2a9cb59 | |||
76bfa34c45 | |||
43d9623877 | |||
60b431459c | |||
6e7b0a5430 | |||
86b36d7a13 | |||
7e122ceec6 | |||
fe0eba9107 | |||
1d1c051a44 | |||
fbd22003a8 | |||
3cfda32b5e | |||
9b1592b335 | |||
fbf50ecc8c | |||
7025a33097 | |||
171024428b | |||
2e4c86be4b | |||
97d5fb84fc | |||
b2c512687a | |||
8526d4d77e | |||
ed1429afa1 | |||
1270f34596 | |||
6eef188d3c | |||
8e23ce1b83 | |||
15ef50e46c | |||
0597152352 | |||
23bb980173 | |||
a846c38695 | |||
1f7f4490b2 | |||
40b220c821 | |||
cb4a631df0 | |||
35718db46f | |||
1ba0891f71 | |||
b36ada0f5b | |||
9cd2158c72 | |||
928134da7a | |||
52a3367b5e | |||
7e7087e94e | |||
9cd8afe90a | |||
526bd02189 | |||
3826fd793d | |||
a6d7e9b839 | |||
29d0384a90 | |||
0481f43746 | |||
f021908f8b | |||
f82d58bbfc | |||
9385f1145f | |||
2acd99b04c | |||
6cd7fb9e5b | |||
540bf4a5c4 | |||
a360afe08a | |||
b66a1f6ba1 | |||
b66932fcec | |||
de38df32c2 | |||
bdfbda7cda | |||
0c49ab392d | |||
b2c0753fdf | |||
c97095be68 | |||
c2b9967691 | |||
ee074f334e | |||
23429d8da4 | |||
e34ac70a72 | |||
77d45334ac | |||
88719c4ccc | |||
386c5a8fa5 | |||
5caa9bed51 | |||
59b90b1328 | |||
05c05868c6 | |||
88d6d907d8 | |||
6cc8fdf215 | |||
02a0cac85a | |||
0976804fdf | |||
f8ff5df2f3 | |||
22acba5aa8 | |||
2bcce234a8 | |||
5859763f04 | |||
4cc0805036 | |||
830ddb21b5 | |||
b31bd93e7d | |||
a89e6b2cdc | |||
dd3ea3dab5 | |||
c3179b3b22 | |||
5c98c1c51e | |||
ff69cdd253 | |||
38e55d55b3 | |||
6f45085d86 | |||
0348f81ba8 | |||
7ee858110c | |||
89637e7d2f | |||
ff3da5f657 | |||
b3ab0bde05 | |||
26dda8dbf9 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -16,4 +16,3 @@ stamp-h1
|
|||||||
build/toxic
|
build/toxic
|
||||||
build/*.o
|
build/*.o
|
||||||
build/*.d
|
build/*.d
|
||||||
apidoc/python/build
|
|
||||||
|
30
INSTALL.md
30
INSTALL.md
@ -1,53 +1,57 @@
|
|||||||
# Installation
|
# Installation
|
||||||
* [Dependencies](#dependencies)
|
* [Dependencies](#deps)
|
||||||
* [OS X Notes](#os-x-notes)
|
* [OS X Notes](#deps_osx)
|
||||||
* [Compiling](#compiling)
|
* [Compiling](#compiling)
|
||||||
* [Documentation](#documentation)
|
* [Documentation](#docs)
|
||||||
* [Notes](#notes)
|
* [Notes](#notes)
|
||||||
* [Compilation variables](#compilation-variables)
|
* [Compilation variables](#comp_vars)
|
||||||
* [Packaging](#packaging)
|
* [Packaging](#packaging)
|
||||||
|
|
||||||
|
<a name="deps" />
|
||||||
## Dependencies
|
## Dependencies
|
||||||
| Name | Needed by | Debian package |
|
| Name | Needed by | Debian package |
|
||||||
|------------------------------------------------------|----------------------------|---------------------|
|
|------------------------------------------------------|----------------------------|---------------------|
|
||||||
| [Tox Core](https://github.com/toktok/c-toxcore) | BASE | *None* |
|
| [Tox Core](https://github.com/irungentoo/toxcore) | BASE | *None* |
|
||||||
| [NCurses](https://www.gnu.org/software/ncurses) | BASE | libncursesw5-dev |
|
| [NCurses](https://www.gnu.org/software/ncurses) | BASE | libncursesw5-dev |
|
||||||
| [LibConfig](http://www.hyperrealm.com/libconfig) | BASE | libconfig-dev |
|
| [LibConfig](http://www.hyperrealm.com/libconfig) | BASE | libconfig-dev |
|
||||||
| [GNUmake](https://www.gnu.org/software/make) | BASE | make |
|
| [GNUmake](https://www.gnu.org/software/make) | BASE | make |
|
||||||
| [libcurl](http://curl.haxx.se/) | BASE | libcurl4-openssl-dev|
|
| [libcurl](http://curl.haxx.se/) | BASE | libcurl4-openssl-dev|
|
||||||
| [libqrencode](https://fukuchi.org/works/qrencode/) | BASE | libqrencode-dev |
|
| [libqrencode](https://fukuchi.org/works/qrencode/) | BASE | libqrencode-dev |
|
||||||
| [Tox Core AV](https://github.com/toktok/c-toxcore) | AUDIO | *None* |
|
| [Tox Core AV](https://github.com/irungentoo/toxcore) | AUDIO | *None* |
|
||||||
| [OpenAL](http://openal.org) | AUDIO, SOUND NOTIFICATIONS | libopenal-dev |
|
| [OpenAL](http://openal.org) | AUDIO, SOUND NOTIFICATIONS | libopenal-dev |
|
||||||
| [OpenALUT](http://openal.org) | SOUND NOTIFICATIONS | libalut-dev |
|
| [OpenALUT](http://openal.org) | SOUND NOTIFICATIONS | libalut-dev |
|
||||||
| [LibNotify](https://developer.gnome.org/libnotify) | DESKTOP NOTIFICATIONS | libnotify-dev |
|
| [LibNotify](https://developer.gnome.org/libnotify) | DESKTOP NOTIFICATIONS | libnotify-dev |
|
||||||
| [Python 3](http://www.python.org/) | PYTHON | python3-dev |
|
|
||||||
| [AsciiDoc](http://asciidoc.org/index.html) | DOCUMENTATION<sup>1</sup> | asciidoc |
|
| [AsciiDoc](http://asciidoc.org/index.html) | DOCUMENTATION<sup>1</sup> | asciidoc |
|
||||||
|
<sup>1</sup>: see [Documentation](#docs)
|
||||||
|
|
||||||
<sup>1</sup>: see [Documentation](#documentation)
|
<a name="deps_osx" />
|
||||||
|
|
||||||
#### OS X Notes
|
#### OS X Notes
|
||||||
Using [Homebrew](http://brew.sh):
|
Using [Homebrew](http://brew.sh):
|
||||||
```
|
```
|
||||||
brew install openal-soft freealut libconfig
|
brew install openal-soft freealut libconfig
|
||||||
brew install --HEAD https://raw.githubusercontent.com/Tox/homebrew-tox/master/Formula/libtoxcore.rb
|
brew install https://raw.githubusercontent.com/Tox/homebrew-tox/master/Formula/libtoxcore.rb
|
||||||
brew install libnotify
|
brew install https://raw.githubusercontent.com/Homebrew/homebrew-x11/master/libnotify.rb
|
||||||
```
|
```
|
||||||
|
|
||||||
You can omit `libnotify` if you intend to build without desktop notifications enabled.
|
You can omit `libnotify` if you intend to build without desktop notifications enabled.
|
||||||
|
|
||||||
|
<a name="Compiling">
|
||||||
## Compiling
|
## Compiling
|
||||||
```
|
```
|
||||||
make PREFIX="/where/to/install"
|
make PREFIX="/where/to/install"
|
||||||
sudo make install PREFIX="/where/to/install"
|
sudo make install PREFIX="/where/to/install"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<a name="docs" />
|
||||||
#### Documentation
|
#### Documentation
|
||||||
Run `make doc` in the build directory after editing the asciidoc files to regenerate the manpages.<br />
|
Run `make doc` in the build directory after editing the asciidoc files to regenerate the manpages.<br />
|
||||||
**NOTE FOR DEVELOPERS**: asciidoc files and generated manpages will need to be commited together.<br />
|
**NOTE FOR DEVELOPERS**: asciidoc files and generated manpages will need to be commited together.<br />
|
||||||
**NOTE FOR EVERYONE**: [asciidoc](http://asciidoc.org/index.html) (and this step) is only required for regenerating manpages when you modify them.
|
**NOTE FOR EVERYONE**: [asciidoc](http://asciidoc.org/index.html) (and this step) is only required for regenerating manpages when you modify them.
|
||||||
|
|
||||||
|
<a name="notes" />
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
|
<a name="comp_vars" />
|
||||||
#### Compilation variables
|
#### Compilation variables
|
||||||
* You can add specific flags to the Makefile with `USER_CFLAGS=""` and/or `USER_LDFLAGS=""`
|
* You can add specific flags to the Makefile with `USER_CFLAGS=""` and/or `USER_LDFLAGS=""`
|
||||||
* You can pass your own flags to the Makefile with `CFLAGS=""` and/or `LDFLAGS=""` (this will supersede the default ones)
|
* You can pass your own flags to the Makefile with `CFLAGS=""` and/or `LDFLAGS=""` (this will supersede the default ones)
|
||||||
@ -56,11 +60,11 @@ Run `make doc` in the build directory after editing the asciidoc files to regene
|
|||||||
* `DISABLE_AV=1` → build toxic without audio call support
|
* `DISABLE_AV=1` → build toxic without audio call support
|
||||||
* `DISABLE_SOUND_NOTIFY=1` → build toxic without sound notifications support
|
* `DISABLE_SOUND_NOTIFY=1` → build toxic without sound notifications support
|
||||||
* `DISABLE_DESKTOP_NOTIFY=1` → build toxic without desktop notifications support
|
* `DISABLE_DESKTOP_NOTIFY=1` → build toxic without desktop notifications support
|
||||||
* Features excluded from the default build must be explicitly enabled using special variables:
|
|
||||||
* `ENABLE_PYTHON=1` → build toxic with Python scripting support
|
|
||||||
|
|
||||||
|
<a name="packaging" />
|
||||||
#### Packaging
|
#### Packaging
|
||||||
* For packaging purpose, you can use `DESTDIR=""` to specify a directory where to store installed files
|
* For packaging purpose, you can use `DESTDIR=""` to specify a directory where to store installed files
|
||||||
* `DESTDIR=""` can be used in addition to `PREFIX=""`:
|
* `DESTDIR=""` can be used in addition to `PREFIX=""`:
|
||||||
* `DESTDIR=""` is meant to specify a directory where to store installed files (ex: "/tmp/build/pkg")
|
* `DESTDIR=""` is meant to specify a directory where to store installed files (ex: "/tmp/build/pkg")
|
||||||
* `PREFIX=""` is meant to specify a prefix directory for binaries and data files (ex: "/usr/local")
|
* `PREFIX=""` is meant to specify a prefix directory for binaries and data files (ex: "/usr/local")
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
src="https://scan.coverity.com/projects/4975/badge.svg"/>
|
src="https://scan.coverity.com/projects/4975/badge.svg"/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
Toxic is a [Tox](https://tox.chat)-based instant messenging client which formerly resided in the [Tox core repository](https://github.com/toktok/c-toxcore), and is now available as a standalone application.
|
Toxic is a [Tox](https://tox.im)-based instant messenging client which formerly resided in the [Tox core repository](https://github.com/irungentoo/toxcore), and is now available as a standalone application.
|
||||||
|
|
||||||
[](https://i.imgur.com/san99Z2.png)
|
[](https://i.imgur.com/san99Z2.png)
|
||||||
|
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
# Minimal makefile for Sphinx documentation
|
|
||||||
#
|
|
||||||
|
|
||||||
# You can set these variables from the command line.
|
|
||||||
SPHINXOPTS =
|
|
||||||
SPHINXBUILD = sphinx-build
|
|
||||||
SPHINXPROJ = toxic_api
|
|
||||||
SOURCEDIR = source
|
|
||||||
BUILDDIR = build
|
|
||||||
|
|
||||||
# Put it first so that "make" without argument is like "make help".
|
|
||||||
help:
|
|
||||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
||||||
|
|
||||||
.PHONY: help Makefile
|
|
||||||
|
|
||||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
|
||||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
|
||||||
%: Makefile
|
|
||||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
@ -1,157 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# toxic_api documentation build configuration file, created by
|
|
||||||
# sphinx-quickstart on Tue May 16 08:58:24 2017.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
# import os
|
|
||||||
# import sys
|
|
||||||
# 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.
|
|
||||||
extensions = []
|
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
|
||||||
templates_path = ['_templates']
|
|
||||||
|
|
||||||
# The suffix(es) of source filenames.
|
|
||||||
# You can specify multiple suffix as a list of string:
|
|
||||||
#
|
|
||||||
# source_suffix = ['.rst', '.md']
|
|
||||||
source_suffix = '.rst'
|
|
||||||
|
|
||||||
# The master toctree document.
|
|
||||||
master_doc = 'index'
|
|
||||||
|
|
||||||
# General information about the project.
|
|
||||||
project = 'toxic_api'
|
|
||||||
copyright = '2017, Jakob Kreuze'
|
|
||||||
author = 'Jakob Kreuze'
|
|
||||||
|
|
||||||
# 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 = '0.7.2'
|
|
||||||
# The full version, including alpha/beta/rc tags.
|
|
||||||
release = '0.7.2'
|
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
|
||||||
# for a list of supported languages.
|
|
||||||
#
|
|
||||||
# This is also used if you do content translation via gettext catalogs.
|
|
||||||
# Usually you set "language" from the command line for these cases.
|
|
||||||
language = None
|
|
||||||
|
|
||||||
# List of patterns, relative to source directory, that match files and
|
|
||||||
# directories to ignore when looking for source files.
|
|
||||||
# This patterns also effect to html_static_path and html_extra_path
|
|
||||||
exclude_patterns = []
|
|
||||||
|
|
||||||
# The name of the Pygments (syntax highlighting) style to use.
|
|
||||||
pygments_style = 'sphinx'
|
|
||||||
|
|
||||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
|
||||||
todo_include_todos = False
|
|
||||||
|
|
||||||
|
|
||||||
# -- 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 = 'alabaster'
|
|
||||||
|
|
||||||
# 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 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']
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTMLHelp output ------------------------------------------
|
|
||||||
|
|
||||||
# Output file base name for HTML help builder.
|
|
||||||
htmlhelp_basename = 'toxic_apidoc'
|
|
||||||
|
|
||||||
|
|
||||||
# -- 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': '',
|
|
||||||
|
|
||||||
# Latex figure (float) alignment
|
|
||||||
#
|
|
||||||
# 'figure_align': 'htbp',
|
|
||||||
}
|
|
||||||
|
|
||||||
# Grouping the document tree into LaTeX files. List of tuples
|
|
||||||
# (source start file, target name, title,
|
|
||||||
# author, documentclass [howto, manual, or own class]).
|
|
||||||
latex_documents = [
|
|
||||||
(master_doc, 'toxic_api.tex', 'toxic\\_api Documentation',
|
|
||||||
'Jakob Kreuze', 'manual'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for manual page output ---------------------------------------
|
|
||||||
|
|
||||||
# One entry per manual page. List of tuples
|
|
||||||
# (source start file, name, description, authors, manual section).
|
|
||||||
man_pages = [
|
|
||||||
(master_doc, 'toxic_api', 'toxic_api Documentation',
|
|
||||||
[author], 1)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
# -- 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 = [
|
|
||||||
(master_doc, 'toxic_api', 'toxic_api Documentation',
|
|
||||||
author, 'toxic_api', 'One line description of project.',
|
|
||||||
'Miscellaneous'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
|||||||
============
|
|
||||||
API Examples
|
|
||||||
============
|
|
||||||
|
|
||||||
Fortune
|
|
||||||
=======
|
|
||||||
.. literalinclude:: fortune.py
|
|
||||||
:language: python
|
|
@ -1,37 +0,0 @@
|
|||||||
import toxic_api
|
|
||||||
import random
|
|
||||||
|
|
||||||
FORTUNES = [
|
|
||||||
"A bug in the code is worth two in the documentation.",
|
|
||||||
"A bug in the hand is better than one as yet undetected.",
|
|
||||||
"\"A debugged program is one for which you have not yet found the "
|
|
||||||
"conditions that make it fail.\" -- Jerry Ogdin"
|
|
||||||
]
|
|
||||||
|
|
||||||
def send_fortune(args):
|
|
||||||
"""Callback function that sends the contact of the current window a
|
|
||||||
given number of random fortunes.
|
|
||||||
"""
|
|
||||||
if len(args) != 1:
|
|
||||||
toxic_api.display("Only one argument allowed!")
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
count = int(args[0])
|
|
||||||
except ValueError:
|
|
||||||
toxic_api.display("Argument must be a number!")
|
|
||||||
return
|
|
||||||
|
|
||||||
if count < 0 or count > 20:
|
|
||||||
toxic_api.display("Argument is too large!")
|
|
||||||
return
|
|
||||||
|
|
||||||
name = toxic_api.get_nick()
|
|
||||||
|
|
||||||
toxic_api.send("%s has decided to send you %d fortunes:" % (name, count))
|
|
||||||
for _ in range(count):
|
|
||||||
toxic_api.send(random.choice(FORTUNES))
|
|
||||||
|
|
||||||
|
|
||||||
toxic_api.register("/fortune", "Send a fortune to the contact of the current "
|
|
||||||
"window", send_fortune)
|
|
@ -1,9 +0,0 @@
|
|||||||
Toxic Scripting Interface Documentation
|
|
||||||
=======================================
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 2
|
|
||||||
|
|
||||||
intro
|
|
||||||
reference
|
|
||||||
examples
|
|
@ -1,12 +0,0 @@
|
|||||||
=========================
|
|
||||||
Toxic Scripting Interface
|
|
||||||
=========================
|
|
||||||
|
|
||||||
A Python scripting interface to `Toxic <https://github.com/JFreegman/toxic>`_.
|
|
||||||
|
|
||||||
|
|
||||||
Getting Started
|
|
||||||
===============
|
|
||||||
Toxic is compiled with Python support by default. To access the scripting interface, simply import "toxic_api" in your script.
|
|
||||||
|
|
||||||
Scripts can be run by issuing "/run <path>" from toxic, or placing them in the "autorun_path" from your toxic configuration file.
|
|
@ -1,73 +0,0 @@
|
|||||||
=============
|
|
||||||
API Reference
|
|
||||||
=============
|
|
||||||
|
|
||||||
Messages
|
|
||||||
========
|
|
||||||
.. function:: display(msg)
|
|
||||||
|
|
||||||
Display a message to the user through the current window.
|
|
||||||
|
|
||||||
:param msg: The message to display.
|
|
||||||
:type msg: string
|
|
||||||
:rtype: none
|
|
||||||
|
|
||||||
.. function:: send(msg)
|
|
||||||
|
|
||||||
Send a message to the user specified by the currently open conversation.
|
|
||||||
|
|
||||||
:param msg: The message to display.
|
|
||||||
:type msg: string
|
|
||||||
:rtype: none
|
|
||||||
|
|
||||||
|
|
||||||
State
|
|
||||||
=====
|
|
||||||
.. function:: get_nick()
|
|
||||||
|
|
||||||
Return the user's current nickname.
|
|
||||||
|
|
||||||
:rtype: string
|
|
||||||
|
|
||||||
.. function:: get_status()
|
|
||||||
|
|
||||||
Return a string representing the user's current status. Can be either "online", "away", or "busy".
|
|
||||||
|
|
||||||
:rtype: string
|
|
||||||
|
|
||||||
.. function:: get_status_message()
|
|
||||||
|
|
||||||
Return the user's current status message.
|
|
||||||
|
|
||||||
:rtype: string
|
|
||||||
|
|
||||||
.. function:: get_all_friends()
|
|
||||||
|
|
||||||
Return a list of all the user's friends.
|
|
||||||
|
|
||||||
:rtype: list of (string, string) tuples containing the nickname followed by their public key
|
|
||||||
|
|
||||||
|
|
||||||
Commands
|
|
||||||
========
|
|
||||||
.. function:: execute(command, class)
|
|
||||||
|
|
||||||
Executes the given command. The API exports three constants for the class parameter; GLOBAL_COMMAND, CHAT_COMMAND, and GROUPCHAT_COMMAND.
|
|
||||||
|
|
||||||
:param command: The command to execute.
|
|
||||||
:type command: string
|
|
||||||
:param class: The class of the command.
|
|
||||||
:type class: int
|
|
||||||
:rtype: none
|
|
||||||
|
|
||||||
.. function:: register(command, help, callback)
|
|
||||||
|
|
||||||
Register a callback to be executed whenever command is run. The callback function will be called with one argument, a list of arguments from when the user calls the command.
|
|
||||||
|
|
||||||
:param command: The command to listen for.
|
|
||||||
:type command: string
|
|
||||||
:param help: A description of the command to be shown in the help menu.
|
|
||||||
:type help: string
|
|
||||||
:param callback: The function to be called.
|
|
||||||
:type callback: callable
|
|
||||||
:rtype: none
|
|
@ -18,4 +18,4 @@ else ifneq ($(MAKECMDGOALS), clean)
|
|||||||
$(warning WARNING -- Toxic will be compiled without audio support)
|
$(warning WARNING -- Toxic will be compiled without audio support)
|
||||||
$(warning WARNING -- You need these libraries for audio support)
|
$(warning WARNING -- You need these libraries for audio support)
|
||||||
$(warning WARNING -- $(MISSING_AUDIO_LIBS))
|
$(warning WARNING -- $(MISSING_AUDIO_LIBS))
|
||||||
endif
|
endif
|
@ -40,12 +40,6 @@ ifneq ($(QR_PNG), disabled)
|
|||||||
-include $(CHECKS_DIR)/qr_png.mk
|
-include $(CHECKS_DIR)/qr_png.mk
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Check if we want build Python scripting support
|
|
||||||
PYTHON = $(shell if [ -z "$(ENABLE_PYTHON)" ] || [ "$(ENABLE_PYTHON)" = "0" ] ; then echo disabled ; else echo enabled ; fi)
|
|
||||||
ifneq ($(PYTHON), disabled)
|
|
||||||
-include $(CHECKS_DIR)/python.mk
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Check if we can build Toxic
|
# Check if we can build Toxic
|
||||||
CHECK_LIBS = $(shell $(PKG_CONFIG) --exists $(LIBS) || echo -n "error")
|
CHECK_LIBS = $(shell $(PKG_CONFIG) --exists $(LIBS) || echo -n "error")
|
||||||
ifneq ($(CHECK_LIBS), error)
|
ifneq ($(CHECK_LIBS), error)
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
# Variables for Python scripting support
|
|
||||||
PYTHON3_LIBS = python3
|
|
||||||
PYTHON_CFLAGS = -DPYTHON
|
|
||||||
PYTHON_OBJ = api.o python_api.o
|
|
||||||
|
|
||||||
# Check if we can build Python scripting support
|
|
||||||
CHECK_PYTHON3_LIBS = $(shell $(PKG_CONFIG) --exists $(PYTHON3_LIBS) || echo -n "error")
|
|
||||||
ifneq ($(CHECK_PYTHON3_LIBS), error)
|
|
||||||
LDFLAGS += $(shell python3-config --ldflags)
|
|
||||||
CFLAGS += $(PYTHON_CFLAGS) $(shell python3-config --includes)
|
|
||||||
OBJ += $(PYTHON_OBJ)
|
|
||||||
else ifneq ($(MAKECMDGOALS), clean)
|
|
||||||
$(warning WARNING -- Toxic will be compiled without Python scripting support)
|
|
||||||
$(warning WARNING -- You need python3 installed for Python scripting support)
|
|
||||||
endif
|
|
@ -1,5 +1,5 @@
|
|||||||
# Version
|
# Version
|
||||||
TOXIC_VERSION = 0.7.2
|
TOXIC_VERSION = 0.7.1
|
||||||
REV = $(shell git rev-list HEAD --count 2>/dev/null || echo -n "error")
|
REV = $(shell git rev-list HEAD --count 2>/dev/null || echo -n "error")
|
||||||
ifneq (, $(findstring error, $(REV)))
|
ifneq (, $(findstring error, $(REV)))
|
||||||
VERSION = $(TOXIC_VERSION)
|
VERSION = $(TOXIC_VERSION)
|
||||||
@ -28,6 +28,5 @@ BINDIR = $(PREFIX)/bin
|
|||||||
DATADIR = $(PREFIX)/share/toxic
|
DATADIR = $(PREFIX)/share/toxic
|
||||||
MANDIR = $(PREFIX)/share/man
|
MANDIR = $(PREFIX)/share/man
|
||||||
APPDIR = $(PREFIX)/share/applications
|
APPDIR = $(PREFIX)/share/applications
|
||||||
|
|
||||||
# Platform tools
|
# Platform tools
|
||||||
PKG_CONFIG = pkg-config
|
PKG_CONFIG = pkg-config
|
||||||
|
@ -15,7 +15,6 @@ help:
|
|||||||
@echo " DISABLE_SOUND_NOTIFY: Set to \"1\" to force building without sound notification support"
|
@echo " DISABLE_SOUND_NOTIFY: Set to \"1\" to force building without sound notification support"
|
||||||
@echo " DISABLE_DESKTOP_NOTIFY: Set to \"1\" to force building without desktop notifications support"
|
@echo " DISABLE_DESKTOP_NOTIFY: Set to \"1\" to force building without desktop notifications support"
|
||||||
@echo " DISABLE_QRPNG: Set to \"1\" to force building without QR exported as PNG support"
|
@echo " DISABLE_QRPNG: Set to \"1\" to force building without QR exported as PNG support"
|
||||||
@echo " ENABLE_PYTHON: Set to \"1\" to enable building with Python scripting support"
|
|
||||||
@echo " USER_CFLAGS: Add custom flags to default CFLAGS"
|
@echo " USER_CFLAGS: Add custom flags to default CFLAGS"
|
||||||
@echo " USER_LDFLAGS: Add custom flags to default LDFLAGS"
|
@echo " USER_LDFLAGS: Add custom flags to default LDFLAGS"
|
||||||
@echo " PREFIX: Specify a prefix directory for binaries, data files,... (default is \"$(abspath $(PREFIX))\")"
|
@echo " PREFIX: Specify a prefix directory for binaries, data files,... (default is \"$(abspath $(PREFIX))\")"
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
'\" t
|
'\" t
|
||||||
.\" Title: toxic.conf
|
.\" Title: toxic.conf
|
||||||
.\" Author: [see the "AUTHORS" section]
|
.\" Author: [see the "AUTHORS" section]
|
||||||
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
|
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
|
||||||
.\" Date: 2016-09-20
|
.\" Date: 2016-07-21
|
||||||
.\" Manual: Toxic Manual
|
.\" Manual: Toxic Manual
|
||||||
.\" Source: toxic __VERSION__
|
.\" Source: toxic __VERSION__
|
||||||
.\" Language: English
|
.\" Language: English
|
||||||
.\"
|
.\"
|
||||||
.TH "TOXIC\&.CONF" "5" "2016\-09\-20" "toxic __VERSION__" "Toxic Manual"
|
.TH "TOXIC\&.CONF" "5" "2016\-07\-21" "toxic __VERSION__" "Toxic Manual"
|
||||||
.\" -----------------------------------------------------------------
|
.\" -----------------------------------------------------------------
|
||||||
.\" * Define some portability stuff
|
.\" * Define some portability stuff
|
||||||
.\" -----------------------------------------------------------------
|
.\" -----------------------------------------------------------------
|
||||||
@ -148,6 +148,11 @@ Indicator for alert messages\&.
|
|||||||
Indicator for normal messages\&.
|
Indicator for normal messages\&.
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
|
\fBline_special\fR
|
||||||
|
.RS 4
|
||||||
|
Indicator for special messages\&.
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
\fBmplex_away\fR
|
\fBmplex_away\fR
|
||||||
.RS 4
|
.RS 4
|
||||||
Set user status when attaching and detaching from GNU screen or tmux\&. true or false
|
Set user status when attaching and detaching from GNU screen or tmux\&. true or false
|
||||||
@ -227,11 +232,6 @@ Default path for downloads\&. String value\&. Absolute path for downloaded files
|
|||||||
Path for your avatar (file must be a \&.png and cannot exceed 16\&.3 KiB)
|
Path for your avatar (file must be a \&.png and cannot exceed 16\&.3 KiB)
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
\fBautorun_path\fR
|
|
||||||
.RS 4
|
|
||||||
Path for any scripts that should be run on startup
|
|
||||||
.RE
|
|
||||||
.PP
|
|
||||||
\fBchatlogs_path\fR
|
\fBchatlogs_path\fR
|
||||||
.RS 4
|
.RS 4
|
||||||
Default path for chatlogs\&. String value\&. Absolute path for chatlog files\&.
|
Default path for chatlogs\&. String value\&. Absolute path for chatlog files\&.
|
||||||
|
@ -94,6 +94,9 @@ OPTIONS
|
|||||||
*line_normal*;;
|
*line_normal*;;
|
||||||
Indicator for normal messages.
|
Indicator for normal messages.
|
||||||
|
|
||||||
|
*line_special*;;
|
||||||
|
Indicator for special messages.
|
||||||
|
|
||||||
*mplex_away*;;
|
*mplex_away*;;
|
||||||
Set user status when attaching and detaching from GNU screen or tmux.
|
Set user status when attaching and detaching from GNU screen or tmux.
|
||||||
true or false
|
true or false
|
||||||
@ -143,9 +146,6 @@ OPTIONS
|
|||||||
*avatar_path*;;
|
*avatar_path*;;
|
||||||
Path for your avatar (file must be a .png and cannot exceed 16.3 KiB)
|
Path for your avatar (file must be a .png and cannot exceed 16.3 KiB)
|
||||||
|
|
||||||
*autorun_path*;;
|
|
||||||
Path for any scripts that should be run on startup
|
|
||||||
|
|
||||||
*chatlogs_path*;;
|
*chatlogs_path*;;
|
||||||
Default path for chatlogs. String value. Absolute path for chatlog files.
|
Default path for chatlogs. String value. Absolute path for chatlog files.
|
||||||
|
|
||||||
|
@ -62,6 +62,9 @@ ui = {
|
|||||||
// Indicator for normal messages.
|
// Indicator for normal messages.
|
||||||
line_normal="---";
|
line_normal="---";
|
||||||
|
|
||||||
|
// Indicator for special messages (currently only used for private group messages)
|
||||||
|
line_special=">>>";
|
||||||
|
|
||||||
// true to change status based on screen/tmux attach/detach, false to disable
|
// true to change status based on screen/tmux attach/detach, false to disable
|
||||||
mplex_away=true;
|
mplex_away=true;
|
||||||
|
|
||||||
@ -87,9 +90,6 @@ tox = {
|
|||||||
// Path for your avatar (file must be a .png and cannot exceed 64 KiB)
|
// Path for your avatar (file must be a .png and cannot exceed 64 KiB)
|
||||||
// avatar_path="/home/USERNAME/Pictures/youravatar.png";
|
// avatar_path="/home/USERNAME/Pictures/youravatar.png";
|
||||||
|
|
||||||
// Path for scripts that should be run on startup
|
|
||||||
// autorun_path="/home/USERNAME/toxic_scripts/";
|
|
||||||
|
|
||||||
// Path for chatlogs
|
// Path for chatlogs
|
||||||
// chatlogs_path="/home/USERNAME/toxic_chatlogs/";
|
// chatlogs_path="/home/USERNAME/toxic_chatlogs/";
|
||||||
};
|
};
|
||||||
@ -121,3 +121,4 @@ keys = {
|
|||||||
toggle_peerlist="Ctrl+b";
|
toggle_peerlist="Ctrl+b";
|
||||||
toggle_paste_mode="Ctrl+T";
|
toggle_paste_mode="Ctrl+T";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
208
src/api.c
208
src/api.c
@ -1,208 +0,0 @@
|
|||||||
/* api.c
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Copyright (C) 2017 Jakob Kreuze <jakob@memeware.net>
|
|
||||||
*
|
|
||||||
* This file is part of Toxic.
|
|
||||||
*
|
|
||||||
* Toxic is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Toxic is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Toxic. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <tox/tox.h>
|
|
||||||
|
|
||||||
#include "execute.h"
|
|
||||||
#include "friendlist.h"
|
|
||||||
#include "line_info.h"
|
|
||||||
#include "message_queue.h"
|
|
||||||
#include "misc_tools.h"
|
|
||||||
#include "python_api.h"
|
|
||||||
#include "settings.h"
|
|
||||||
#include "toxic_strings.h"
|
|
||||||
#include "windows.h"
|
|
||||||
|
|
||||||
Tox *user_tox;
|
|
||||||
static WINDOW *cur_window;
|
|
||||||
static ToxWindow *self_window;
|
|
||||||
|
|
||||||
extern FriendsList Friends;
|
|
||||||
extern struct user_settings *user_settings;
|
|
||||||
|
|
||||||
void api_display(const char *const msg)
|
|
||||||
{
|
|
||||||
if (msg == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
self_window = get_active_window();
|
|
||||||
line_info_add(self_window, NULL, NULL, NULL, SYS_MSG, 0, 0, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
FriendsList api_get_friendslist(void)
|
|
||||||
{
|
|
||||||
return Friends;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *api_get_nick(void)
|
|
||||||
{
|
|
||||||
size_t len = tox_self_get_name_size(user_tox);
|
|
||||||
uint8_t *name = malloc(len + 1);
|
|
||||||
|
|
||||||
if (name == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
tox_self_get_name(user_tox, name);
|
|
||||||
name[len] = '\0';
|
|
||||||
return (char *) name;
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_USER_STATUS api_get_status(void)
|
|
||||||
{
|
|
||||||
return tox_self_get_status(user_tox);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *api_get_status_message(void)
|
|
||||||
{
|
|
||||||
size_t len = tox_self_get_status_message_size(user_tox);
|
|
||||||
uint8_t *status = malloc(len + 1);
|
|
||||||
|
|
||||||
if (status == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
tox_self_get_status_message(user_tox, status);
|
|
||||||
status[len] = '\0';
|
|
||||||
return (char *) status;
|
|
||||||
}
|
|
||||||
|
|
||||||
void api_send(const char *msg)
|
|
||||||
{
|
|
||||||
if (msg == NULL || self_window->chatwin->cqueue == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
char *name = api_get_nick();
|
|
||||||
char timefrmt[TIME_STR_SIZE];
|
|
||||||
|
|
||||||
if (name == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
self_window = get_active_window();
|
|
||||||
get_time_str(timefrmt, sizeof(timefrmt));
|
|
||||||
|
|
||||||
strncpy((char *) self_window->chatwin->line, msg, sizeof(self_window->chatwin->line));
|
|
||||||
add_line_to_hist(self_window->chatwin);
|
|
||||||
line_info_add(self_window, timefrmt, name, NULL, OUT_MSG, 0, 0, "%s", msg);
|
|
||||||
cqueue_add(self_window->chatwin->cqueue, msg, strlen(msg), OUT_MSG,
|
|
||||||
self_window->chatwin->hst->line_end->id + 1);
|
|
||||||
free(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void api_execute(const char *input, int mode)
|
|
||||||
{
|
|
||||||
self_window = get_active_window();
|
|
||||||
execute(cur_window, self_window, user_tox, input, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
int do_plugin_command(int num_args, char (*args)[MAX_STR_SIZE])
|
|
||||||
{
|
|
||||||
return do_python_command(num_args, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
int num_registered_handlers(void)
|
|
||||||
{
|
|
||||||
return python_num_registered_handlers();
|
|
||||||
}
|
|
||||||
|
|
||||||
int help_max_width(void)
|
|
||||||
{
|
|
||||||
return python_help_max_width();
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw_handler_help(WINDOW *win)
|
|
||||||
{
|
|
||||||
python_draw_handler_help(win);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cmd_run(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
const char *error_str;
|
|
||||||
|
|
||||||
cur_window = window;
|
|
||||||
self_window = self;
|
|
||||||
|
|
||||||
if ( argc != 1 ) {
|
|
||||||
if ( argc < 1 ) error_str = "Path must be specified!";
|
|
||||||
else error_str = "Only one argument allowed!";
|
|
||||||
|
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, error_str);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fp = fopen(argv[1], "r");
|
|
||||||
|
|
||||||
if ( fp == NULL ) {
|
|
||||||
error_str = "Path does not exist!";
|
|
||||||
|
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, error_str);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
run_python(fp, argv[1]);
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void invoke_autoruns(WINDOW *window, ToxWindow *self)
|
|
||||||
{
|
|
||||||
struct dirent *dir;
|
|
||||||
char abspath_buf[PATH_MAX + 1], err_buf[PATH_MAX + 1];
|
|
||||||
size_t path_len;
|
|
||||||
DIR *d;
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
if (user_settings->autorun_path[0] == '\0')
|
|
||||||
return;
|
|
||||||
|
|
||||||
d = opendir(user_settings->autorun_path);
|
|
||||||
|
|
||||||
if (d == NULL) {
|
|
||||||
snprintf(err_buf, PATH_MAX + 1, "Autorun path does not exist: %s", user_settings->autorun_path);
|
|
||||||
api_display(err_buf);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_window = window;
|
|
||||||
self_window = self;
|
|
||||||
|
|
||||||
while ((dir = readdir(d)) != NULL) {
|
|
||||||
path_len = strlen(dir->d_name);
|
|
||||||
|
|
||||||
if (!strcmp(dir->d_name + path_len - 3, ".py")) {
|
|
||||||
snprintf(abspath_buf, PATH_MAX + 1, "%s%s", user_settings->autorun_path, dir->d_name);
|
|
||||||
fp = fopen(abspath_buf, "r");
|
|
||||||
|
|
||||||
if (fp == NULL) {
|
|
||||||
snprintf(err_buf, PATH_MAX + 1, "Invalid path: %s", abspath_buf);
|
|
||||||
api_display(err_buf);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
run_python(fp, abspath_buf);
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir(d);
|
|
||||||
}
|
|
42
src/api.h
42
src/api.h
@ -1,42 +0,0 @@
|
|||||||
/* api.h
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Copyright (C) 2017 Jakob Kreuze <jakob@memeware.net>
|
|
||||||
*
|
|
||||||
* This file is part of Toxic.
|
|
||||||
*
|
|
||||||
* Toxic is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Toxic is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Toxic. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef API_H
|
|
||||||
#define API_H
|
|
||||||
|
|
||||||
#include "friendlist.h"
|
|
||||||
#include "windows.h"
|
|
||||||
|
|
||||||
void api_display(const char *const msg);
|
|
||||||
FriendsList api_get_friendslist(void);
|
|
||||||
char *api_get_nick(void);
|
|
||||||
TOX_USER_STATUS api_get_status(void);
|
|
||||||
char *api_get_status_message(void);
|
|
||||||
void api_send(const char *msg);
|
|
||||||
void api_execute(const char *input, int mode);
|
|
||||||
int do_plugin_command(int num_args, char (*args)[MAX_STR_SIZE]);
|
|
||||||
int num_registered_handlers(void);
|
|
||||||
int help_max_width(void);
|
|
||||||
void draw_handler_help(WINDOW *win);
|
|
||||||
void invoke_autoruns(WINDOW *w, ToxWindow *self);
|
|
||||||
|
|
||||||
#endif /* #define API_H */
|
|
@ -110,10 +110,6 @@ int complete_line(ToxWindow *self, const void *list, int n_items, int size)
|
|||||||
bool dir_search = !strncmp(ubuf, "/sendfile", strlen("/sendfile"))
|
bool dir_search = !strncmp(ubuf, "/sendfile", strlen("/sendfile"))
|
||||||
|| !strncmp(ubuf, "/avatar", strlen("/avatar"));
|
|| !strncmp(ubuf, "/avatar", strlen("/avatar"));
|
||||||
|
|
||||||
#ifdef PYTHON
|
|
||||||
dir_search = dir_search || !strncmp(ubuf, "/run", strlen("/run"));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* isolate substring from space behind pos to pos */
|
/* isolate substring from space behind pos to pos */
|
||||||
char tmp[MAX_STR_SIZE];
|
char tmp[MAX_STR_SIZE];
|
||||||
snprintf(tmp, sizeof(tmp), "%s", ubuf);
|
snprintf(tmp, sizeof(tmp), "%s", ubuf);
|
||||||
|
@ -477,7 +477,7 @@ void *load_nodeslist_thread(void *data)
|
|||||||
/* If nodeslist does not contain any valid entries we set the last_scan value
|
/* If nodeslist does not contain any valid entries we set the last_scan value
|
||||||
* to 0 so that it will fetch a new list the next time this function is called.
|
* to 0 so that it will fetch a new list the next time this function is called.
|
||||||
*/
|
*/
|
||||||
if (Nodes.count == 0) {
|
if (idx == 0) {
|
||||||
const char *s = "{\"last_scan\":0}";
|
const char *s = "{\"last_scan\":0}";
|
||||||
rewind(fp);
|
rewind(fp);
|
||||||
fwrite(s, strlen(s), 1, fp); // Not much we can do if it fails
|
fwrite(s, strlen(s), 1, fp); // Not much we can do if it fails
|
||||||
|
48
src/chat.c
48
src/chat.c
@ -65,14 +65,10 @@ static void init_infobox(ToxWindow *self);
|
|||||||
static void kill_infobox(ToxWindow *self);
|
static void kill_infobox(ToxWindow *self);
|
||||||
#endif /* AUDIO */
|
#endif /* AUDIO */
|
||||||
|
|
||||||
#if defined(AUDIO) && defined(PYTHON)
|
#ifdef AUDIO
|
||||||
#define AC_NUM_CHAT_COMMANDS 31
|
#define AC_NUM_CHAT_COMMANDS 31
|
||||||
#elif AUDIO
|
|
||||||
#define AC_NUM_CHAT_COMMANDS 30
|
|
||||||
#elif PYTHON
|
|
||||||
#define AC_NUM_CHAT_COMMANDS 23
|
|
||||||
#else
|
#else
|
||||||
#define AC_NUM_CHAT_COMMANDS 22
|
#define AC_NUM_CHAT_COMMANDS 23
|
||||||
#endif /* AUDIO */
|
#endif /* AUDIO */
|
||||||
|
|
||||||
/* Array of chat command names used for tab completion. */
|
/* Array of chat command names used for tab completion. */
|
||||||
@ -85,6 +81,7 @@ static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = {
|
|||||||
{ "/close" },
|
{ "/close" },
|
||||||
{ "/connect" },
|
{ "/connect" },
|
||||||
{ "/exit" },
|
{ "/exit" },
|
||||||
|
{ "/gaccept" },
|
||||||
{ "/group" },
|
{ "/group" },
|
||||||
{ "/help" },
|
{ "/help" },
|
||||||
{ "/invite" },
|
{ "/invite" },
|
||||||
@ -112,12 +109,6 @@ static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = {
|
|||||||
{ "/video" },
|
{ "/video" },
|
||||||
|
|
||||||
#endif /* AUDIO */
|
#endif /* AUDIO */
|
||||||
|
|
||||||
#ifdef PYTHON
|
|
||||||
|
|
||||||
{ "/run" },
|
|
||||||
|
|
||||||
#endif /* PYTHON */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void set_self_typingstatus(ToxWindow *self, Tox *m, bool is_typing)
|
static void set_self_typingstatus(ToxWindow *self, Tox *m, bool is_typing)
|
||||||
@ -619,25 +610,18 @@ static void chat_onFileRecv(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_
|
|||||||
&self->active_box, self->name, "Incoming file: %s", filename );
|
&self->active_box, self->name, "Incoming file: %s", filename );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, uint8_t type, const char *group_pub_key,
|
static void chat_onGroupInvite(ToxWindow *self, Tox *m, uint32_t friendnumber, const char *invite_data,
|
||||||
uint16_t length)
|
size_t length)
|
||||||
{
|
{
|
||||||
if (self->num != friendnumber)
|
if (self->num != friendnumber)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (Friends.list[friendnumber].group_invite.key != NULL)
|
if (Friends.list[friendnumber].group_invite.data)
|
||||||
free(Friends.list[friendnumber].group_invite.key);
|
free(Friends.list[friendnumber].group_invite.data);
|
||||||
|
|
||||||
char *k = malloc(length);
|
Friends.list[friendnumber].group_invite.data = malloc(length * sizeof(uint8_t));
|
||||||
|
memcpy(Friends.list[friendnumber].group_invite.data, invite_data, length);
|
||||||
if (k == NULL)
|
|
||||||
exit_toxic_err("Failed in chat_onGroupInvite", FATALERR_MEMORY);
|
|
||||||
|
|
||||||
memcpy(k, group_pub_key, length);
|
|
||||||
Friends.list[friendnumber].group_invite.key = k;
|
|
||||||
Friends.list[friendnumber].group_invite.pending = true;
|
|
||||||
Friends.list[friendnumber].group_invite.length = length;
|
Friends.list[friendnumber].group_invite.length = length;
|
||||||
Friends.list[friendnumber].group_invite.type = type;
|
|
||||||
|
|
||||||
sound_notify(self, generic_message, NT_WNDALERT_2 | user_settings->bell_on_invite, NULL);
|
sound_notify(self, generic_message, NT_WNDALERT_2 | user_settings->bell_on_invite, NULL);
|
||||||
|
|
||||||
@ -650,7 +634,7 @@ static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, ui
|
|||||||
box_silent_notify(self, NT_WNDALERT_2 | NT_NOFOCUS, &self->active_box, name, "invites you to join group chat");
|
box_silent_notify(self, NT_WNDALERT_2 | NT_NOFOCUS, &self->active_box, name, "invites you to join group chat");
|
||||||
|
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s has invited you to a group chat.", name);
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s has invited you to a group chat.", name);
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type \"/join\" to join the chat.");
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type \"/gaccept\" to join the chat.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* AV Stuff */
|
/* AV Stuff */
|
||||||
@ -941,15 +925,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
|||||||
diff = dir_match(self, m, ctx->line, L"/sendfile");
|
diff = dir_match(self, m, ctx->line, L"/sendfile");
|
||||||
} else if (wcsncmp(ctx->line, L"/avatar \"", wcslen(L"/avatar \"")) == 0) {
|
} else if (wcsncmp(ctx->line, L"/avatar \"", wcslen(L"/avatar \"")) == 0) {
|
||||||
diff = dir_match(self, m, ctx->line, L"/avatar");
|
diff = dir_match(self, m, ctx->line, L"/avatar");
|
||||||
}
|
} else if (wcsncmp(ctx->line, L"/status ", wcslen(L"/status ")) == 0) {
|
||||||
|
|
||||||
#ifdef PYTHON
|
|
||||||
else if (wcsncmp(ctx->line, L"/run \"", wcslen(L"/run \"")) == 0) {
|
|
||||||
diff = dir_match(self, m, ctx->line, L"/run");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
else if (wcsncmp(ctx->line, L"/status ", wcslen(L"/status ")) == 0) {
|
|
||||||
const char status_cmd_list[3][8] = {
|
const char status_cmd_list[3][8] = {
|
||||||
{"online"},
|
{"online"},
|
||||||
{"away"},
|
{"away"},
|
||||||
@ -1224,7 +1200,6 @@ ToxWindow new_chat(Tox *m, uint32_t friendnum)
|
|||||||
ret.onMessage = &chat_onMessage;
|
ret.onMessage = &chat_onMessage;
|
||||||
ret.onConnectionChange = &chat_onConnectionChange;
|
ret.onConnectionChange = &chat_onConnectionChange;
|
||||||
ret.onTypingChange = & chat_onTypingChange;
|
ret.onTypingChange = & chat_onTypingChange;
|
||||||
ret.onGroupInvite = &chat_onGroupInvite;
|
|
||||||
ret.onNickChange = &chat_onNickChange;
|
ret.onNickChange = &chat_onNickChange;
|
||||||
ret.onStatusChange = &chat_onStatusChange;
|
ret.onStatusChange = &chat_onStatusChange;
|
||||||
ret.onStatusMessageChange = &chat_onStatusMessageChange;
|
ret.onStatusMessageChange = &chat_onStatusMessageChange;
|
||||||
@ -1233,6 +1208,7 @@ ToxWindow new_chat(Tox *m, uint32_t friendnum)
|
|||||||
ret.onFileControl = &chat_onFileControl;
|
ret.onFileControl = &chat_onFileControl;
|
||||||
ret.onFileRecv = &chat_onFileRecv;
|
ret.onFileRecv = &chat_onFileRecv;
|
||||||
ret.onReadReceipt = &chat_onReadReceipt;
|
ret.onReadReceipt = &chat_onReadReceipt;
|
||||||
|
ret.onGroupInvite = &chat_onGroupInvite;
|
||||||
|
|
||||||
#ifdef AUDIO
|
#ifdef AUDIO
|
||||||
ret.onInvite = &chat_onInvite;
|
ret.onInvite = &chat_onInvite;
|
||||||
|
@ -78,6 +78,47 @@ void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar
|
|||||||
close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, silent);
|
close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, silent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cmd_groupaccept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
|
{
|
||||||
|
if (get_num_active_windows() >= MAX_WINDOWS_NUM) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Warning: Too many windows are open.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Friends.list[self->num].group_invite.length == 0) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending group invite");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *passwd = NULL;
|
||||||
|
uint16_t passwd_len = 0;
|
||||||
|
|
||||||
|
if (argc > 0) {
|
||||||
|
passwd = argv[1];
|
||||||
|
passwd_len = strlen(passwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_INVITE_ACCEPT err;
|
||||||
|
uint32_t groupnumber = tox_group_invite_accept(m, Friends.list[self->num].group_invite.data,
|
||||||
|
Friends.list[self->num].group_invite.length,
|
||||||
|
(uint8_t *) passwd, passwd_len, &err);
|
||||||
|
|
||||||
|
if (err != TOX_ERR_GROUP_INVITE_ACCEPT_OK) {
|
||||||
|
if (err == TOX_ERR_GROUP_INVITE_ACCEPT_TOO_LONG)
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to joing group: Password too long.");
|
||||||
|
else
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to joing group (error %d).", err);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (init_groupchat_win(m, groupnumber, NULL, 0) == -1) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize.");
|
||||||
|
tox_group_leave(m, groupnumber, NULL, 0, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
{
|
{
|
||||||
if (argc < 1) {
|
if (argc < 1) {
|
||||||
@ -85,61 +126,24 @@ void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*a
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
long int groupnum = strtol(argv[1], NULL, 10);
|
int groupnum = atoi(argv[1]);
|
||||||
|
|
||||||
if ((groupnum == 0 && strcmp(argv[1], "0")) || groupnum < 0 || groupnum == LONG_MAX) {
|
|
||||||
|
if (groupnum == 0 && strcmp(argv[1], "0")) { /* atoi returns 0 value on invalid input */
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid group number.");
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid group number.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TOX_ERR_CONFERENCE_INVITE err;
|
TOX_ERR_GROUP_INVITE_FRIEND err;
|
||||||
|
|
||||||
if (!tox_conference_invite(m, self->num, groupnum, &err)) {
|
if (!tox_group_invite_friend(m, groupnum, self->num, &err)) {
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to invite contact to group (error %d)", err);
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to invite contact to group (error %d).", err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invited contact to Group %d.", groupnum);
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invited contact to Group %d.", groupnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmd_join_group(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
|
||||||
{
|
|
||||||
if (get_num_active_windows() >= MAX_WINDOWS_NUM) {
|
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Warning: Too many windows are open.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *groupkey = Friends.list[self->num].group_invite.key;
|
|
||||||
uint16_t length = Friends.list[self->num].group_invite.length;
|
|
||||||
uint8_t type = Friends.list[self->num].group_invite.type;
|
|
||||||
|
|
||||||
if (!Friends.list[self->num].group_invite.pending) {
|
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending group chat invite.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type != TOX_CONFERENCE_TYPE_TEXT) {
|
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Toxic does not support audio groups.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_CONFERENCE_JOIN err;
|
|
||||||
|
|
||||||
uint32_t groupnum = tox_conference_join(m, self->num, (uint8_t *) groupkey, length, &err);
|
|
||||||
|
|
||||||
if (err != TOX_ERR_CONFERENCE_JOIN_OK) {
|
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize (error %d)", err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (init_groupchat_win(prompt, m, groupnum, type) == -1) {
|
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize.");
|
|
||||||
tox_conference_delete(m, groupnum, NULL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
{
|
{
|
||||||
if (argc < 1) {
|
if (argc < 1) {
|
||||||
|
@ -26,9 +26,9 @@
|
|||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
#include "toxic.h"
|
#include "toxic.h"
|
||||||
|
|
||||||
|
void cmd_groupaccept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
void cmd_groupinvite(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
|
||||||
void cmd_join_group(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
|
||||||
void cmd_savefile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
void cmd_savefile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
void cmd_sendfile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
void cmd_sendfile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
|
||||||
|
120
src/execute.c
120
src/execute.c
@ -33,7 +33,8 @@
|
|||||||
#include "line_info.h"
|
#include "line_info.h"
|
||||||
#include "misc_tools.h"
|
#include "misc_tools.h"
|
||||||
#include "notify.h"
|
#include "notify.h"
|
||||||
#include "api.h"
|
|
||||||
|
#define MAX_NUM_ARGS 10 /* Includes command */
|
||||||
|
|
||||||
struct cmd_func {
|
struct cmd_func {
|
||||||
const char *name;
|
const char *name;
|
||||||
@ -50,6 +51,7 @@ static struct cmd_func global_commands[] = {
|
|||||||
{ "/exit", cmd_quit },
|
{ "/exit", cmd_quit },
|
||||||
{ "/group", cmd_groupchat },
|
{ "/group", cmd_groupchat },
|
||||||
{ "/help", cmd_prompt_help },
|
{ "/help", cmd_prompt_help },
|
||||||
|
{ "/join", cmd_join },
|
||||||
{ "/log", cmd_log },
|
{ "/log", cmd_log },
|
||||||
{ "/myid", cmd_myid },
|
{ "/myid", cmd_myid },
|
||||||
{ "/myqr", cmd_myqr },
|
{ "/myqr", cmd_myqr },
|
||||||
@ -68,16 +70,13 @@ static struct cmd_func global_commands[] = {
|
|||||||
{ "/lsvdev", cmd_list_video_devices },
|
{ "/lsvdev", cmd_list_video_devices },
|
||||||
{ "/svdev" , cmd_change_video_device },
|
{ "/svdev" , cmd_change_video_device },
|
||||||
#endif /* VIDEO */
|
#endif /* VIDEO */
|
||||||
#ifdef PYTHON
|
|
||||||
{ "/run", cmd_run },
|
|
||||||
#endif /* PYTHON */
|
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct cmd_func chat_commands[] = {
|
static struct cmd_func chat_commands[] = {
|
||||||
{ "/cancel", cmd_cancelfile },
|
{ "/cancel", cmd_cancelfile },
|
||||||
|
{ "/gaccept", cmd_groupaccept },
|
||||||
{ "/invite", cmd_groupinvite },
|
{ "/invite", cmd_groupinvite },
|
||||||
{ "/join", cmd_join_group },
|
|
||||||
{ "/savefile", cmd_savefile },
|
{ "/savefile", cmd_savefile },
|
||||||
{ "/sendfile", cmd_sendfile },
|
{ "/sendfile", cmd_sendfile },
|
||||||
#ifdef AUDIO
|
#ifdef AUDIO
|
||||||
@ -95,19 +94,99 @@ static struct cmd_func chat_commands[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct cmd_func group_commands[] = {
|
static struct cmd_func group_commands[] = {
|
||||||
{ "/title", cmd_set_title },
|
{ "/ban", cmd_ban },
|
||||||
|
{ "/chatid", cmd_chatid },
|
||||||
|
{ "/ignore", cmd_ignore },
|
||||||
|
{ "/kick", cmd_kick },
|
||||||
|
{ "/mod", cmd_mod },
|
||||||
|
{ "/mykey", cmd_mykey },
|
||||||
|
{ "/passwd", cmd_set_passwd },
|
||||||
|
{ "/peerlimit", cmd_set_peerlimit },
|
||||||
|
{ "/privacy", cmd_set_privacy },
|
||||||
|
{ "/rejoin", cmd_rejoin },
|
||||||
|
{ "/silence", cmd_silence },
|
||||||
|
{ "/topic", cmd_set_topic },
|
||||||
|
{ "/unban", cmd_unban },
|
||||||
|
{ "/unignore", cmd_unignore },
|
||||||
|
{ "/unmod", cmd_unmod },
|
||||||
|
{ "/unsilence", cmd_unsilence },
|
||||||
|
{ "/whois", cmd_whois },
|
||||||
#ifdef AUDIO
|
#ifdef AUDIO
|
||||||
{ "/mute", cmd_mute },
|
{ "/mute", cmd_mute },
|
||||||
{ "/sense", cmd_sense },
|
{ "/sense", cmd_sense },
|
||||||
#endif /* AUDIO */
|
#endif /* AUDIO */
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Parses input command and puts args into arg array.
|
#define NUM_SPECIAL_COMMANDS 15
|
||||||
Returns number of arguments on success, -1 on failure. */
|
static const char special_commands[NUM_SPECIAL_COMMANDS][MAX_CMDNAME_SIZE] = {
|
||||||
|
"/ban",
|
||||||
|
"/gaccept",
|
||||||
|
"/group",
|
||||||
|
"/ignore",
|
||||||
|
"/kick",
|
||||||
|
"/mod",
|
||||||
|
"/nick",
|
||||||
|
"/note",
|
||||||
|
"/passwd",
|
||||||
|
"/silence",
|
||||||
|
"/topic",
|
||||||
|
"/unignore",
|
||||||
|
"/unmod",
|
||||||
|
"/unsilence",
|
||||||
|
"/whois",
|
||||||
|
};
|
||||||
|
|
||||||
|
/* return true if input command is in the special_commands array. False otherwise.*/
|
||||||
|
static bool is_special_command(const char *input)
|
||||||
|
{
|
||||||
|
int s = char_find(0, input, ' ');
|
||||||
|
|
||||||
|
if (s == strlen(input))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_SPECIAL_COMMANDS; ++i) {
|
||||||
|
if (strncmp(input, special_commands[i], s) == 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parses commands in the special_commands array which take exactly one argument that may contain spaces.
|
||||||
|
* Unlike parse_command, this function does not split the input string at spaces.
|
||||||
|
*
|
||||||
|
* Returns number of arguments on success
|
||||||
|
* Returns -1 on failure
|
||||||
|
*/
|
||||||
|
static int parse_special_command(WINDOW *w, ToxWindow *self, const char *input, char (*args)[MAX_STR_SIZE])
|
||||||
|
{
|
||||||
|
int len = strlen(input);
|
||||||
|
int s = char_find(0, input, ' ');
|
||||||
|
|
||||||
|
if (s + 1 >= len)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
memcpy(args[0], input, s);
|
||||||
|
args[0][s++] = '\0'; /* increment to remove space after /command */
|
||||||
|
memcpy(args[1], input + s, len - s);
|
||||||
|
args[1][len - s] = '\0';
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parses input command and puts args (split by spaces) into args array.
|
||||||
|
*
|
||||||
|
* Returns number of arguments on success
|
||||||
|
* Returns -1 on failure.
|
||||||
|
*/
|
||||||
static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*args)[MAX_STR_SIZE])
|
static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*args)[MAX_STR_SIZE])
|
||||||
{
|
{
|
||||||
|
if (is_special_command(input))
|
||||||
|
return parse_special_command(w, self, input, args);
|
||||||
|
|
||||||
char *cmd = strdup(input);
|
char *cmd = strdup(input);
|
||||||
|
|
||||||
if (cmd == NULL)
|
if (cmd == NULL)
|
||||||
@ -145,11 +224,19 @@ static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*a
|
|||||||
strcpy(cmd, tmp); /* tmp will always fit inside cmd */
|
strcpy(cmd, tmp); /* tmp will always fit inside cmd */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ugly special case concatinates all args after arg1 for multi-word group passwords */
|
||||||
|
if (num_args > 2 && strcmp(args[0], "/join") == 0)
|
||||||
|
strcpy(args[2], input + strlen(args[0]) + 1 + strlen(args[1]) + 1);
|
||||||
|
|
||||||
free(cmd);
|
free(cmd);
|
||||||
return num_args;
|
return num_args;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Matches command to respective function. Returns 0 on match, 1 on no match */
|
/* Matches command to respective function.
|
||||||
|
*
|
||||||
|
* Returns 0 on match,
|
||||||
|
* Returns -1 on no match
|
||||||
|
*/
|
||||||
static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, struct cmd_func *commands,
|
static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, struct cmd_func *commands,
|
||||||
char (*args)[MAX_STR_SIZE])
|
char (*args)[MAX_STR_SIZE])
|
||||||
{
|
{
|
||||||
@ -162,7 +249,7 @@ static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, struct c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode)
|
void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode)
|
||||||
@ -197,10 +284,5 @@ void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode)
|
|||||||
if (do_command(w, self, m, num_args, global_commands, args) == 0)
|
if (do_command(w, self, m, num_args, global_commands, args) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef PYTHON
|
|
||||||
if (do_plugin_command(num_args, args) == 0)
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid command.");
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid command.");
|
||||||
}
|
}
|
||||||
|
@ -26,13 +26,11 @@
|
|||||||
#include "toxic.h"
|
#include "toxic.h"
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
|
|
||||||
#define MAX_NUM_ARGS 4 /* Includes command */
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
GLOBAL_COMMAND_MODE,
|
GLOBAL_COMMAND_MODE,
|
||||||
CHAT_COMMAND_MODE,
|
CHAT_COMMAND_MODE,
|
||||||
GROUPCHAT_COMMAND_MODE,
|
GROUPCHAT_COMMAND_MODE,
|
||||||
};
|
} COMMAND_MODE;
|
||||||
|
|
||||||
void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode);
|
void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode);
|
||||||
|
|
||||||
|
@ -113,11 +113,11 @@ static void realloc_blocklist(int n)
|
|||||||
|
|
||||||
void kill_friendlist(void)
|
void kill_friendlist(void)
|
||||||
{
|
{
|
||||||
int i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < Friends.max_idx; ++i) {
|
for (i = 0; i < Friends.max_idx; ++i) {
|
||||||
if (Friends.list[i].active && Friends.list[i].group_invite.key != NULL)
|
if (Friends.list[i].group_invite.data != NULL)
|
||||||
free(Friends.list[i].group_invite.key);
|
free(Friends.list[i].group_invite.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
realloc_blocklist(0);
|
realloc_blocklist(0);
|
||||||
@ -520,8 +520,7 @@ static void friendlist_onFileRecv(ToxWindow *self, Tox *m, uint32_t num, uint32_
|
|||||||
sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL);
|
sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, uint8_t type, const char *group_pub_key,
|
static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, uint32_t num, const char *data, size_t length)
|
||||||
uint16_t length)
|
|
||||||
{
|
{
|
||||||
if (num >= Friends.max_idx)
|
if (num >= Friends.max_idx)
|
||||||
return;
|
return;
|
||||||
@ -581,9 +580,6 @@ static void delete_friend(Tox *m, uint32_t f_num)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Friends.list[f_num].group_invite.key != NULL)
|
|
||||||
free(Friends.list[f_num].group_invite.key);
|
|
||||||
|
|
||||||
memset(&Friends.list[f_num], 0, sizeof(ToxicFriend));
|
memset(&Friends.list[f_num], 0, sizeof(ToxicFriend));
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
@ -35,11 +35,9 @@ struct LastOnline {
|
|||||||
char hour_min_str[TIME_STR_SIZE]; /* holds 12/24-hour time string e.g. "10:43 PM" */
|
char hour_min_str[TIME_STR_SIZE]; /* holds 12/24-hour time string e.g. "10:43 PM" */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GroupChatInvite {
|
struct GroupInvite {
|
||||||
char *key;
|
uint8_t *data;
|
||||||
uint16_t length;
|
uint16_t length;
|
||||||
uint8_t type;
|
|
||||||
bool pending;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -57,7 +55,7 @@ typedef struct {
|
|||||||
uint8_t status;
|
uint8_t status;
|
||||||
|
|
||||||
struct LastOnline last_online;
|
struct LastOnline last_online;
|
||||||
struct GroupChatInvite group_invite;
|
struct GroupInvite group_invite;
|
||||||
|
|
||||||
struct FileTransfer file_receiver[MAX_FILES];
|
struct FileTransfer file_receiver[MAX_FILES];
|
||||||
struct FileTransfer file_sender[MAX_FILES];
|
struct FileTransfer file_sender[MAX_FILES];
|
||||||
|
@ -329,42 +329,133 @@ void cmd_groupchat(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (argc < 1) {
|
if (argc < 1) {
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Please specify group type: text | audio");
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group name required");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t type;
|
const char *tmp_name = argv[1];
|
||||||
|
int len = strlen(tmp_name);
|
||||||
|
|
||||||
if (!strcasecmp(argv[1], "audio"))
|
if (len == 0 || len > TOX_GROUP_MAX_GROUP_NAME_LENGTH) {
|
||||||
type = TOX_CONFERENCE_TYPE_AV;
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid group name.");
|
||||||
else if (!strcasecmp(argv[1], "text"))
|
|
||||||
type = TOX_CONFERENCE_TYPE_TEXT;
|
|
||||||
else {
|
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Valid group types are: text | audio");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != TOX_CONFERENCE_TYPE_TEXT) {
|
char name[TOX_GROUP_MAX_GROUP_NAME_LENGTH];
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Toxic does not support audio groups.");
|
|
||||||
|
if (argv[1][0] == '\"') { /* remove opening and closing quotes */
|
||||||
|
snprintf(name, sizeof(name), "%s", &argv[1][1]);
|
||||||
|
len -= 2;
|
||||||
|
name[len] = '\0';
|
||||||
|
} else {
|
||||||
|
snprintf(name, sizeof(name), "%s", argv[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_NEW err;
|
||||||
|
uint32_t groupnum = tox_group_new(m, TOX_GROUP_PRIVACY_STATE_PUBLIC, (uint8_t *) name, len, &err);
|
||||||
|
|
||||||
|
if (err != TOX_ERR_GROUP_NEW_OK) {
|
||||||
|
switch (err) {
|
||||||
|
case TOX_ERR_GROUP_NEW_TOO_LONG: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group name length cannot exceed %d.",
|
||||||
|
TOX_GROUP_MAX_GROUP_NAME_LENGTH);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOX_ERR_GROUP_NEW_EMPTY: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group name cannot be empty.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize (error %d).", err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TOX_ERR_CONFERENCE_NEW err;
|
int init = init_groupchat_win(m, groupnum, name, len);
|
||||||
|
|
||||||
uint32_t groupnum = tox_conference_new(m, &err);
|
if (init == -1) {
|
||||||
|
|
||||||
if (err != TOX_ERR_CONFERENCE_NEW_OK) {
|
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize (error %d)", err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (init_groupchat_win(prompt, m, groupnum, type) == -1) {
|
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize.");
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize.");
|
||||||
tox_conference_delete(m, groupnum, NULL);
|
tox_group_leave(m, groupnum, NULL, 0, NULL);
|
||||||
|
} else if (init == -2) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,
|
||||||
|
"You have been kicked from a group. Close the window and try again.");
|
||||||
|
tox_group_leave(m, groupnum, NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
|
{
|
||||||
|
if (get_num_active_windows() >= MAX_WINDOWS_NUM) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Warning: Too many windows are open.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat [%d] created.", groupnum);
|
if (argc < 1) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Chat ID is required.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *chat_id = argv[1];
|
||||||
|
|
||||||
|
if (strlen(chat_id) != TOX_GROUP_CHAT_ID_SIZE * 2) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid chat ID");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char id_bin[TOX_GROUP_CHAT_ID_SIZE] = {0};
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
char xch[3];
|
||||||
|
uint32_t x;
|
||||||
|
|
||||||
|
for (i = 0; i < TOX_GROUP_CHAT_ID_SIZE; ++i) {
|
||||||
|
xch[0] = chat_id[2 * i];
|
||||||
|
xch[1] = chat_id[2 * i + 1];
|
||||||
|
xch[2] = '\0';
|
||||||
|
|
||||||
|
if (sscanf(xch, "%02x", &x) != 1) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid chat ID.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
id_bin[i] = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *passwd = NULL;
|
||||||
|
uint16_t passwd_len = 0;
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
passwd = argv[2];
|
||||||
|
passwd_len = strlen(passwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_JOIN err;
|
||||||
|
uint32_t groupnum = tox_group_join(m, (uint8_t *) id_bin, (uint8_t *) passwd, passwd_len, &err);
|
||||||
|
|
||||||
|
if (err != TOX_ERR_GROUP_JOIN_OK) {
|
||||||
|
if (err == TOX_ERR_GROUP_JOIN_TOO_LONG)
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Password length cannot exceed %d.", TOX_GROUP_MAX_PASSWORD_SIZE);
|
||||||
|
else
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to join group (error %d).", err);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int init = init_groupchat_win(m, groupnum, NULL, 0);
|
||||||
|
|
||||||
|
if (init == -1) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize.");
|
||||||
|
tox_group_leave(m, groupnum, NULL, 0, NULL);
|
||||||
|
} else if (init == -2) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,
|
||||||
|
"You have been kicked from a group. Close the window and try again.");
|
||||||
|
tox_group_leave(m, groupnum, NULL, 0, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
@ -518,6 +609,7 @@ void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
|
|||||||
|
|
||||||
tox_self_set_name(m, (uint8_t *) nick, len, NULL);
|
tox_self_set_name(m, (uint8_t *) nick, len, NULL);
|
||||||
prompt_update_nick(prompt, nick);
|
prompt_update_nick(prompt, nick);
|
||||||
|
set_nick_all_groups(m, nick, len);
|
||||||
|
|
||||||
store_data(m, DATA_FILE);
|
store_data(m, DATA_FILE);
|
||||||
}
|
}
|
||||||
@ -529,19 +621,7 @@ void cmd_note(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argv[1][0] != '\"') {
|
prompt_update_statusmessage(prompt, m, argv[1]);
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Note must be enclosed in quotes.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* remove opening and closing quotes and replace linebreaks with spaces */
|
|
||||||
char msg[MAX_STR_SIZE];
|
|
||||||
snprintf(msg, sizeof(msg), "%s", &argv[1][1]);
|
|
||||||
int len = strlen(msg) - 1;
|
|
||||||
msg[len] = '\0';
|
|
||||||
strsubst(msg, '\n', ' ');
|
|
||||||
|
|
||||||
prompt_update_statusmessage(prompt, m, msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmd_nospam(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
void cmd_nospam(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
@ -641,6 +721,7 @@ void cmd_status(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
|
|||||||
|
|
||||||
tox_self_set_status(m, status);
|
tox_self_set_status(m, status);
|
||||||
prompt_update_status(prompt, status);
|
prompt_update_status(prompt, status);
|
||||||
|
set_status_all_groups(m, status);
|
||||||
|
|
||||||
if (have_note) {
|
if (have_note) {
|
||||||
if (argv[2][0] != '\"') {
|
if (argv[2][0] != '\"') {
|
||||||
|
@ -33,6 +33,7 @@ void cmd_clear(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE
|
|||||||
void cmd_connect(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
void cmd_connect(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
void cmd_decline(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
void cmd_decline(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
void cmd_groupchat(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
void cmd_groupchat(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
void cmd_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
void cmd_log(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
void cmd_log(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
void cmd_myid(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
void cmd_myid(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
void cmd_myqr(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
void cmd_myqr(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
@ -56,8 +57,4 @@ void cmd_list_video_devices(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)
|
|||||||
void cmd_change_video_device(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
void cmd_change_video_device(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
#endif /* VIDEO */
|
#endif /* VIDEO */
|
||||||
|
|
||||||
#ifdef PYTHON
|
|
||||||
void cmd_run(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* #define GLOBAL_COMMANDS_H */
|
#endif /* #define GLOBAL_COMMANDS_H */
|
||||||
|
@ -21,66 +21,707 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include "toxic.h"
|
#include "toxic.h"
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
#include "line_info.h"
|
#include "line_info.h"
|
||||||
#include "misc_tools.h"
|
#include "misc_tools.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "groupchat.h"
|
||||||
|
|
||||||
void cmd_set_title(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
extern GroupChat groupchats[MAX_GROUPCHAT_NUM];
|
||||||
|
|
||||||
|
void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
{
|
{
|
||||||
TOX_ERR_CONFERENCE_TITLE err;
|
char chatid[TOX_GROUP_CHAT_ID_SIZE * 2 + 1] = {0};
|
||||||
char title[MAX_STR_SIZE];
|
char chat_public_key[TOX_GROUP_CHAT_ID_SIZE];
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_STATE_QUERIES err;
|
||||||
|
|
||||||
|
if (!tox_group_get_chat_id(m, self->num, (uint8_t *) chat_public_key, &err)) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve the Chat ID (error %d).", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < TOX_GROUP_CHAT_ID_SIZE; ++i) {
|
||||||
|
char xx[3];
|
||||||
|
snprintf(xx, sizeof(xx), "%02X", chat_public_key[i] & 0xff);
|
||||||
|
strcat(chatid, xx);
|
||||||
|
}
|
||||||
|
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", chatid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
|
{
|
||||||
if (argc < 1) {
|
if (argc < 1) {
|
||||||
size_t tlen = tox_conference_get_title_size(m, self->num, &err);
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified.");
|
||||||
|
|
||||||
if (err != TOX_ERR_CONFERENCE_TITLE_OK) {
|
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Title is not set");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tox_conference_get_title(m, self->num, (uint8_t *) title, &err)) {
|
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Title is not set");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
title[tlen] = '\0';
|
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Title is set to: %s", title);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argv[1][0] != '\"') {
|
const char *nick = argv[1];
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Title must be enclosed in quotes.");
|
uint32_t peer_id;
|
||||||
|
|
||||||
|
if (group_get_nick_peer_id(self->num, nick, &peer_id) == -1) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remove opening and closing quotes */
|
TOX_ERR_GROUP_TOGGLE_IGNORE err;
|
||||||
snprintf(title, sizeof(title), "%s", &argv[1][1]);
|
|
||||||
int len = strlen(title) - 1;
|
|
||||||
title[len] = '\0';
|
|
||||||
|
|
||||||
if (!tox_conference_set_title(m, self->num, (uint8_t *) title, len, &err)) {
|
if (!tox_group_toggle_ignore(m, self->num, peer_id, true, &err)) {
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set title (error %d)", err);
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to ignore %s (error %d).", nick, err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_window_title(self, title, len);
|
|
||||||
|
|
||||||
char timefrmt[TIME_STR_SIZE];
|
char timefrmt[TIME_STR_SIZE];
|
||||||
char selfnick[TOX_MAX_NAME_LENGTH];
|
|
||||||
|
|
||||||
get_time_str(timefrmt, sizeof(timefrmt));
|
get_time_str(timefrmt, sizeof(timefrmt));
|
||||||
|
|
||||||
tox_self_get_name(m, (uint8_t *) selfnick);
|
line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- Ignoring %s", nick);
|
||||||
size_t sn_len = tox_self_get_name_size(m);
|
}
|
||||||
|
|
||||||
|
static void cmd_kickban_helper(ToxWindow *self, Tox *m, const char *nick, bool set_ban)
|
||||||
|
{
|
||||||
|
uint32_t peer_id;
|
||||||
|
|
||||||
|
if (group_get_nick_peer_id(self->num, nick, &peer_id) == -1) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *type_str = set_ban ? "ban" : "kick";
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_MOD_REMOVE_PEER err;
|
||||||
|
tox_group_mod_remove_peer(m, self->num, peer_id, set_ban, &err);
|
||||||
|
|
||||||
|
switch (err) {
|
||||||
|
case TOX_ERR_GROUP_MOD_REMOVE_PEER_OK: {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOX_ERR_GROUP_MOD_REMOVE_PEER_PERMISSIONS: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to %s %s.", type_str, nick);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to %s %s from the group (error %d).", type_str, nick,
|
||||||
|
err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
|
{
|
||||||
|
if (argc < 1) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_kickban_helper(self, m, argv[1], false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_ban(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
|
{
|
||||||
|
TOX_ERR_GROUP_BAN_QUERY err;
|
||||||
|
|
||||||
|
if (argc < 1) {
|
||||||
|
size_t num_banned = tox_group_ban_get_list_size(m, self->num, &err);
|
||||||
|
|
||||||
|
if (err != TOX_ERR_GROUP_BAN_QUERY_OK) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to get the ban list size (error %d).", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_banned == 0) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban list is empty.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ban_list[num_banned];
|
||||||
|
|
||||||
|
if (!tox_group_ban_get_list(m, self->num, ban_list, &err)) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to get the ban list (error %d).", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_banned; ++i) {
|
||||||
|
uint32_t id = ban_list[i];
|
||||||
|
size_t len = tox_group_ban_get_name_size(m, self->num, id, &err);
|
||||||
|
|
||||||
|
if (err != TOX_ERR_GROUP_BAN_QUERY_OK) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve name length for ban %d (error %d).", id, err);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char tmp_nick[len];
|
||||||
|
|
||||||
|
if (!tox_group_ban_get_name(m, self->num, id, (uint8_t *) tmp_nick, &err)) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve name for ban %d (error %d).", id, err);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char nick[len + 1];
|
||||||
|
copy_tox_str(nick, sizeof(nick), tmp_nick, len);
|
||||||
|
|
||||||
|
uint64_t time_set = tox_group_ban_get_time_set(m, self->num, id, &err);
|
||||||
|
|
||||||
|
if (err != TOX_ERR_GROUP_BAN_QUERY_OK) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve timestamp for ban %d (error %d).", id, err);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tm tm_set = *localtime((const time_t *) &time_set);
|
||||||
|
|
||||||
|
char time_str[64];
|
||||||
|
|
||||||
|
strftime(time_str, sizeof(time_str), "%e %b %Y %H:%M:%S%p", &tm_set);
|
||||||
|
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "ID %d : %s [Set:%s]", id, nick, time_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_kickban_helper(self, m, argv[1], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_unban(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
|
{
|
||||||
|
if (argc < 1) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban ID must be specified.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ban_id = atoi(argv[1]);
|
||||||
|
|
||||||
|
if (ban_id == 0 && strcmp(argv[1], "0")) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban ID must be a non-negative interger.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_MOD_REMOVE_BAN err;
|
||||||
|
tox_group_mod_remove_ban(m, self->num, ban_id, &err);
|
||||||
|
|
||||||
|
switch (err) {
|
||||||
|
case TOX_ERR_GROUP_MOD_REMOVE_BAN_OK: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban list entry with id %d has been removed.", ban_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOX_ERR_GROUP_MOD_REMOVE_BAN_PERMISSIONS: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to unban peers.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOX_ERR_GROUP_MOD_REMOVE_BAN_FAIL_ACTION: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban ID does not exist.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to remove ban list entry (error %d).", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_mod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
|
{
|
||||||
|
if (argc < 1) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *nick = argv[1];
|
||||||
|
uint32_t peer_id;
|
||||||
|
|
||||||
|
if (group_get_nick_peer_id(self->num, nick, &peer_id) == -1) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_MOD_SET_ROLE err;
|
||||||
|
tox_group_mod_set_role(m, self->num, peer_id, TOX_GROUP_ROLE_MODERATOR, &err);
|
||||||
|
|
||||||
|
switch (err) {
|
||||||
|
case TOX_ERR_GROUP_MOD_SET_ROLE_OK: {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to promote moderators.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOX_ERR_GROUP_MOD_SET_ROLE_ASSIGNMENT: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "This peer is already a moderator.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to promote peer to moderator (error %d).", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_unmod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
|
{
|
||||||
|
if (argc < 1) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *nick = argv[1];
|
||||||
|
uint32_t peer_id;
|
||||||
|
|
||||||
|
if (group_get_nick_peer_id(self->num, nick, &peer_id) == -1) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tox_group_peer_get_role(m, self->num, peer_id, NULL) != TOX_GROUP_ROLE_MODERATOR) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s is not a moderator", nick);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_MOD_SET_ROLE err;
|
||||||
|
tox_group_mod_set_role(m, self->num, peer_id, TOX_GROUP_ROLE_USER, &err);
|
||||||
|
|
||||||
|
switch (err) {
|
||||||
|
case TOX_ERR_GROUP_MOD_SET_ROLE_OK: {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Nice try.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to revoke moderator powers from %s (error %d).", nick,
|
||||||
|
err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_mykey(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
|
{
|
||||||
|
char pk_string[TOX_GROUP_PEER_PUBLIC_KEY_SIZE * 2 + 1] = {0};
|
||||||
|
char pk[TOX_GROUP_PEER_PUBLIC_KEY_SIZE];
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_SELF_QUERY err;
|
||||||
|
|
||||||
|
if (!tox_group_self_get_public_key(m, self->num, (uint8_t *) pk, &err)) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to fetch your public key (error %d)", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < TOX_GROUP_PEER_PUBLIC_KEY_SIZE; ++i) {
|
||||||
|
char d[3];
|
||||||
|
snprintf(d, sizeof(d), "%02X", pk[i] & 0xff);
|
||||||
|
strcat(pk_string, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", pk_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_set_passwd(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
|
{
|
||||||
|
const char *passwd = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
if (argc > 0) {
|
||||||
|
passwd = argv[1];
|
||||||
|
len = strlen(passwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_FOUNDER_SET_PASSWORD err;
|
||||||
|
tox_group_founder_set_password(m, self->num, (uint8_t *) passwd, len, &err);
|
||||||
|
|
||||||
|
switch (err) {
|
||||||
|
case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK: {
|
||||||
|
if (len > 0)
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Password has been set to %s.", passwd);
|
||||||
|
else
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Password has been unset.");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_TOO_LONG: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Password length must not exceed %d.",
|
||||||
|
TOX_GROUP_MAX_PASSWORD_SIZE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_PERMISSIONS: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to set the password.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set password (error %d).", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_set_peerlimit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
|
{
|
||||||
|
int maxpeers = 0;
|
||||||
|
|
||||||
|
if (argc < 1) {
|
||||||
|
TOX_ERR_GROUP_STATE_QUERIES err;
|
||||||
|
uint32_t maxpeers = tox_group_get_peer_limit(m, self->num, &err);
|
||||||
|
|
||||||
|
if (err != TOX_ERR_GROUP_STATE_QUERIES_OK) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve peer limit (error %d).", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer limit is set to %d", maxpeers);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
maxpeers = atoi(argv[1]);
|
||||||
|
|
||||||
|
if (maxpeers <= 0) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer limit must be a value greater than 0.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT err;
|
||||||
|
tox_group_founder_set_peer_limit(m, self->num, maxpeers, &err);
|
||||||
|
|
||||||
|
switch (err) {
|
||||||
|
case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer limit has been set to %d.", maxpeers);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_PERMISSIONS: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to set the peer limit.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set the peer limit (error %d).", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_set_privacy(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
|
{
|
||||||
|
const char *pstate_str = NULL;
|
||||||
|
TOX_GROUP_PRIVACY_STATE privacy_state;
|
||||||
|
|
||||||
|
if (argc < 1) {
|
||||||
|
TOX_ERR_GROUP_STATE_QUERIES err;
|
||||||
|
privacy_state = tox_group_get_privacy_state(m, self->num, &err);
|
||||||
|
|
||||||
|
if (err != TOX_ERR_GROUP_STATE_QUERIES_OK) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve privacy state (error %d).", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pstate_str = privacy_state == TOX_GROUP_PRIVACY_STATE_PRIVATE ? "private" : "public";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Privacy state is set to %s.", pstate_str);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pstate_str = argv[1];
|
||||||
|
|
||||||
|
if (strcasecmp(pstate_str, "private") != 0 && strcasecmp(pstate_str, "public") != 0) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Privacy state must be \"private\" or \"public\".");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
privacy_state = strcasecmp(pstate_str,
|
||||||
|
"private") == 0 ? TOX_GROUP_PRIVACY_STATE_PRIVATE : TOX_GROUP_PRIVACY_STATE_PUBLIC;
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE err;
|
||||||
|
tox_group_founder_set_privacy_state(m, self->num, privacy_state, &err);
|
||||||
|
|
||||||
|
switch (err) {
|
||||||
|
case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Privacy state has been set to %s.", pstate_str);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_PERMISSIONS: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to set the privacy state.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error setting privacy state (error %d).", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_silence(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
|
{
|
||||||
|
if (argc < 1) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *nick = argv[1];
|
||||||
|
uint32_t peer_id;
|
||||||
|
|
||||||
|
if (group_get_nick_peer_id(self->num, nick, &peer_id) == -1) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_MOD_SET_ROLE err;
|
||||||
|
tox_group_mod_set_role(m, self->num, peer_id, TOX_GROUP_ROLE_OBSERVER, &err);
|
||||||
|
|
||||||
|
switch (err) {
|
||||||
|
case TOX_ERR_GROUP_MOD_SET_ROLE_OK: {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to silence %s.", nick);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to silence %s (error %d).", nick, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_unsilence(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
|
{
|
||||||
|
if (argc < 1) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *nick = argv[1];
|
||||||
|
uint32_t peer_id;
|
||||||
|
|
||||||
|
if (group_get_nick_peer_id(self->num, nick, &peer_id) == -1) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tox_group_peer_get_role(m, self->num, peer_id, NULL) != TOX_GROUP_ROLE_OBSERVER) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s is not silenced.", nick);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_MOD_SET_ROLE err;
|
||||||
|
tox_group_mod_set_role(m, self->num, peer_id, TOX_GROUP_ROLE_USER, &err);
|
||||||
|
|
||||||
|
switch (err) {
|
||||||
|
case TOX_ERR_GROUP_MOD_SET_ROLE_OK: {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to unsilence %s.", nick);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to unsilence %s (error %d).", nick, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_rejoin(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
|
{
|
||||||
|
TOX_ERR_GROUP_RECONNECT err;
|
||||||
|
|
||||||
|
if (!tox_group_reconnect(m, self->num, &err)) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to rejoin group (error %d).", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Reconnecting to group...");
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
|
{
|
||||||
|
if (argc < 1) {
|
||||||
|
TOX_ERR_GROUP_STATE_QUERIES err;
|
||||||
|
size_t tlen = tox_group_get_topic_size(m, self->num, &err);
|
||||||
|
|
||||||
|
if (err != TOX_ERR_GROUP_STATE_QUERIES_OK) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve topic length (error %d).", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tlen > 0) {
|
||||||
|
char cur_topic[tlen];
|
||||||
|
|
||||||
|
if (!tox_group_get_topic(m, self->num, (uint8_t *) cur_topic, &err)) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve topic (error %d).", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_topic[tlen] = '\0';
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Topic is set to: %s", cur_topic);
|
||||||
|
} else {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Topic is not set.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *topic = argv[1];
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_TOPIC_SET err;
|
||||||
|
tox_group_set_topic(m, self->num, (uint8_t *) topic, strlen(topic), &err);
|
||||||
|
|
||||||
|
switch (err) {
|
||||||
|
case TOX_ERR_GROUP_TOPIC_SET_OK: {
|
||||||
|
/* handled below switch */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOX_ERR_GROUP_TOPIC_SET_TOO_LONG: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Topic length must not exceed %d.", TOX_GROUP_MAX_TOPIC_LENGTH);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOX_ERR_GROUP_TOPIC_SET_PERMISSIONS: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to set the topic.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set the topic (error %d).", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char timefrmt[TIME_STR_SIZE];
|
||||||
|
get_time_str(timefrmt, sizeof(timefrmt));
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_SELF_QUERY sn_err;
|
||||||
|
size_t sn_len = tox_group_self_get_name_size(m, self->num, &sn_err);
|
||||||
|
char selfnick[sn_len];
|
||||||
|
|
||||||
|
if (!tox_group_self_get_name(m, self->num, (uint8_t *) selfnick, &sn_err)) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve your own name (error %d).", sn_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
selfnick[sn_len] = '\0';
|
selfnick[sn_len] = '\0';
|
||||||
|
|
||||||
line_info_add(self, timefrmt, selfnick, NULL, NAME_CHANGE, 0, 0, " set the group title to: %s", title);
|
line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, MAGENTA, "-!- You set the topic to: %s", topic);
|
||||||
|
|
||||||
char tmp_event[MAX_STR_SIZE];
|
char tmp_event[MAX_STR_SIZE];
|
||||||
snprintf(tmp_event, sizeof(tmp_event), "set title to %s", title);
|
snprintf(tmp_event, sizeof(tmp_event), "set topic to %s", topic);
|
||||||
write_to_log(tmp_event, selfnick, self->chatwin->log, true);
|
write_to_log(tmp_event, selfnick, self->chatwin->log, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cmd_unignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
|
{
|
||||||
|
if (argc < 1) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer must be specified.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *nick = argv[1];
|
||||||
|
uint32_t peer_id;
|
||||||
|
|
||||||
|
if (group_get_nick_peer_id(self->num, nick, &peer_id) == -1) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_GROUP_TOGGLE_IGNORE err;
|
||||||
|
|
||||||
|
if (!tox_group_toggle_ignore(m, self->num, peer_id, false, &err)) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to unignore %s (error %d).", nick, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char timefrmt[TIME_STR_SIZE];
|
||||||
|
get_time_str(timefrmt, sizeof(timefrmt));
|
||||||
|
|
||||||
|
line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- You are no longer ignoring %s", nick);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_whois(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
|
{
|
||||||
|
if (argc < 1) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer must be specified.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupChat *chat = &groupchats[self->num];
|
||||||
|
|
||||||
|
if (!chat) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Whois failed.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *nick = argv[1];
|
||||||
|
uint32_t peer_id;
|
||||||
|
|
||||||
|
if (group_get_nick_peer_id(self->num, nick, &peer_id) == -1) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int peer_index = get_peer_index(self->num, peer_id);
|
||||||
|
|
||||||
|
if (peer_index < 0) {
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Whois failed.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *status_str = "Online";
|
||||||
|
|
||||||
|
if (chat->peer_list[peer_index].status == TOX_USER_STATUS_BUSY)
|
||||||
|
status_str = "Busy";
|
||||||
|
else if (chat->peer_list[peer_index].status == TOX_USER_STATUS_AWAY)
|
||||||
|
status_str = "Away";
|
||||||
|
|
||||||
|
const char *role_str = "User";
|
||||||
|
|
||||||
|
if (chat->peer_list[peer_index].role == TOX_GROUP_ROLE_FOUNDER)
|
||||||
|
role_str = "Founder";
|
||||||
|
else if (chat->peer_list[peer_index].role == TOX_GROUP_ROLE_MODERATOR)
|
||||||
|
role_str = "Moderator";
|
||||||
|
else if (chat->peer_list[peer_index].role == TOX_GROUP_ROLE_OBSERVER)
|
||||||
|
role_str = "Observer";
|
||||||
|
|
||||||
|
char last_seen_str[128];
|
||||||
|
get_elapsed_time_str_2(last_seen_str, sizeof(last_seen_str), get_unix_time() - chat->peer_list[peer_index].last_active);
|
||||||
|
|
||||||
|
char pk_string[TOX_GROUP_PEER_PUBLIC_KEY_SIZE * 2 + 1] = {0};
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < TOX_GROUP_PEER_PUBLIC_KEY_SIZE; ++i) {
|
||||||
|
char d[3];
|
||||||
|
snprintf(d, sizeof(d), "%02X", chat->peer_list[peer_index].public_key[i] & 0xff);
|
||||||
|
strcat(pk_string, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Whois for %s", nick);
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Role: %s", role_str);
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Status: %s", status_str);
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Last active: %s", last_seen_str);
|
||||||
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Public key: %s", pk_string);
|
||||||
|
}
|
||||||
|
@ -26,6 +26,23 @@
|
|||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
#include "toxic.h"
|
#include "toxic.h"
|
||||||
|
|
||||||
void cmd_set_title(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
void cmd_ban(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
void cmd_mod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
void cmd_mykey(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
void cmd_prune(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
void cmd_set_passwd(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
void cmd_set_peerlimit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
void cmd_set_privacy(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
void cmd_rejoin(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
void cmd_silence(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
void cmd_unsilence(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
void cmd_unban(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
void cmd_unignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
void cmd_unmod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
void cmd_whois(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
|
||||||
#endif /* GROUP_COMMANDS_H */
|
#endif /* GROUP_COMMANDS_H */
|
||||||
|
1225
src/groupchat.c
1225
src/groupchat.c
File diff suppressed because it is too large
Load Diff
@ -31,25 +31,37 @@
|
|||||||
#define MAX_GROUPCHAT_NUM MAX_WINDOWS_NUM - 2
|
#define MAX_GROUPCHAT_NUM MAX_WINDOWS_NUM - 2
|
||||||
#define GROUP_EVENT_WAIT 3
|
#define GROUP_EVENT_WAIT 3
|
||||||
|
|
||||||
|
struct GroupPeer {
|
||||||
|
bool active;
|
||||||
|
char name[TOX_MAX_NAME_LENGTH];
|
||||||
|
size_t name_length;
|
||||||
|
uint32_t peer_id;
|
||||||
|
uint8_t public_key[TOX_GROUP_PEER_PUBLIC_KEY_SIZE];
|
||||||
|
TOX_USER_STATUS status;
|
||||||
|
TOX_GROUP_ROLE role;
|
||||||
|
uint64_t last_active;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int chatwin;
|
struct GroupPeer *peer_list;
|
||||||
bool active;
|
char *name_list; /* List of peer names, needed for tab completion */
|
||||||
uint8_t type;
|
uint32_t num_peers; /* Number of peers in the chat/name_list array */
|
||||||
uint32_t num_peers;
|
uint32_t max_idx; /* Maximum peer list index - 1 */
|
||||||
int side_pos; /* current position of the sidebar - used for scrolling up and down */
|
uint32_t groupnumber;
|
||||||
time_t start_time;
|
int chatwin;
|
||||||
uint8_t *peer_names;
|
bool active;
|
||||||
uint8_t *oldpeer_names;
|
uint64_t time_connected; /* The time we successfully connected to the group */
|
||||||
uint16_t *peer_name_lengths;
|
int side_pos; /* current position of the sidebar - used for scrolling up and down */
|
||||||
uint16_t *oldpeer_name_lengths;
|
|
||||||
} GroupChat;
|
} GroupChat;
|
||||||
|
|
||||||
void close_groupchat(ToxWindow *self, Tox *m, uint32_t groupnum);
|
void close_groupchat(ToxWindow *self, Tox *m, uint32_t groupnum);
|
||||||
int init_groupchat_win(ToxWindow *prompt, Tox *m, uint32_t groupnum, uint8_t type);
|
int init_groupchat_win(Tox *m, uint32_t groupnum, const char *groupname, size_t length);
|
||||||
|
void set_nick_all_groups(Tox *m, const char *nick, size_t length);
|
||||||
|
void set_status_all_groups(Tox *m, uint8_t status);
|
||||||
|
int group_get_nick_peer_id(uint32_t groupnum, const char *nick, uint32_t *peer_id);
|
||||||
|
int get_peer_index(uint32_t groupnum, uint32_t peer_id);
|
||||||
|
|
||||||
/* destroys and re-creates groupchat window with or without the peerlist */
|
/* destroys and re-creates groupchat window */
|
||||||
void redraw_groupchat_win(ToxWindow *self);
|
void redraw_groupchat_win(ToxWindow *self);
|
||||||
|
|
||||||
ToxWindow new_group_chat(Tox *m, uint32_t groupnum);
|
|
||||||
|
|
||||||
#endif /* #define GROUPCHAT_H */
|
#endif /* #define GROUPCHAT_H */
|
||||||
|
104
src/help.c
104
src/help.c
@ -26,13 +26,8 @@
|
|||||||
#include "toxic.h"
|
#include "toxic.h"
|
||||||
#include "help.h"
|
#include "help.h"
|
||||||
#include "misc_tools.h"
|
#include "misc_tools.h"
|
||||||
#include "api.h"
|
|
||||||
|
|
||||||
#ifdef PYTHON
|
|
||||||
#define HELP_MENU_HEIGHT 10
|
|
||||||
#else
|
|
||||||
#define HELP_MENU_HEIGHT 9
|
#define HELP_MENU_HEIGHT 9
|
||||||
#endif /* PYTHON */
|
|
||||||
#define HELP_MENU_WIDTH 26
|
#define HELP_MENU_WIDTH 26
|
||||||
|
|
||||||
void help_init_menu(ToxWindow *self)
|
void help_init_menu(ToxWindow *self)
|
||||||
@ -100,13 +95,6 @@ static void help_draw_menu(ToxWindow *self)
|
|||||||
wattroff(win, A_BOLD | COLOR_PAIR(BLUE));
|
wattroff(win, A_BOLD | COLOR_PAIR(BLUE));
|
||||||
wprintw(win, "oup commands\n");
|
wprintw(win, "oup commands\n");
|
||||||
|
|
||||||
#ifdef PYTHON
|
|
||||||
wattron(win, A_BOLD | COLOR_PAIR(BLUE));
|
|
||||||
wprintw(win, " p");
|
|
||||||
wattroff(win, A_BOLD | COLOR_PAIR(BLUE));
|
|
||||||
wprintw(win, "lugin commands\n");
|
|
||||||
#endif /* PYTHON */
|
|
||||||
|
|
||||||
wattron(win, A_BOLD | COLOR_PAIR(BLUE));
|
wattron(win, A_BOLD | COLOR_PAIR(BLUE));
|
||||||
wprintw(win, " f");
|
wprintw(win, " f");
|
||||||
wattroff(win, A_BOLD | COLOR_PAIR(BLUE));
|
wattroff(win, A_BOLD | COLOR_PAIR(BLUE));
|
||||||
@ -165,10 +153,11 @@ static void help_draw_global(ToxWindow *self)
|
|||||||
wprintw(win, " /connect <ip> <port> <key> : Manually connect to a DHT node\n");
|
wprintw(win, " /connect <ip> <port> <key> : Manually connect to a DHT node\n");
|
||||||
wprintw(win, " /status <type> <msg> : Set status with optional note\n");
|
wprintw(win, " /status <type> <msg> : Set status with optional note\n");
|
||||||
wprintw(win, " /note <msg> : Set a personal note\n");
|
wprintw(win, " /note <msg> : Set a personal note\n");
|
||||||
|
wprintw(win, " /group : Create a group chat\n");
|
||||||
|
wprintw(win, " /join <chat id> <passwd> : Join a group chat with optional password\n");
|
||||||
wprintw(win, " /nick <nick> : Set your nickname\n");
|
wprintw(win, " /nick <nick> : Set your nickname\n");
|
||||||
wprintw(win, " /nospam <value> : Change part of your Tox ID to stop spam\n");
|
wprintw(win, " /nospam <value> : Change part of your Tox ID to stop spam\n");
|
||||||
wprintw(win, " /log <on> or <off> : Enable/disable logging\n");
|
wprintw(win, " /log <on> or <off> : Enable/disable logging\n");
|
||||||
wprintw(win, " /group <type> : Create a group chat where type: text | audio\n");
|
|
||||||
wprintw(win, " /myid : Print your Tox ID\n");
|
wprintw(win, " /myid : Print your Tox ID\n");
|
||||||
#ifdef QRPNG
|
#ifdef QRPNG
|
||||||
wprintw(win, " /myqr <txt> or <png> : Print your Tox ID's QR code to a file.\n");
|
wprintw(win, " /myqr <txt> or <png> : Print your Tox ID's QR code to a file.\n");
|
||||||
@ -197,14 +186,6 @@ static void help_draw_global(ToxWindow *self)
|
|||||||
wprintw(win, " /svdev <type> <id> : Set active video device\n");
|
wprintw(win, " /svdev <type> <id> : Set active video device\n");
|
||||||
#endif /* VIDEO */
|
#endif /* VIDEO */
|
||||||
|
|
||||||
#ifdef PYTHON
|
|
||||||
wattron(win, A_BOLD);
|
|
||||||
wprintw(win, "\n Scripting:\n");
|
|
||||||
wattroff(win, A_BOLD);
|
|
||||||
|
|
||||||
wprintw(win, " /run <path> : Load and run the script at path\n");
|
|
||||||
#endif /* PYTHON */
|
|
||||||
|
|
||||||
help_draw_bottom_menu(win);
|
help_draw_bottom_menu(win);
|
||||||
|
|
||||||
box(win, ACS_VLINE, ACS_HLINE);
|
box(win, ACS_VLINE, ACS_HLINE);
|
||||||
@ -221,8 +202,7 @@ static void help_draw_chat(ToxWindow *self)
|
|||||||
wprintw(win, "Chat Commands:\n");
|
wprintw(win, "Chat Commands:\n");
|
||||||
wattroff(win, A_BOLD | COLOR_PAIR(RED));
|
wattroff(win, A_BOLD | COLOR_PAIR(RED));
|
||||||
|
|
||||||
wprintw(win, " /invite <n> : Invite contact to a group chat\n");
|
wprintw(win, " /gaccept <password> : Accept a group invite with optional password\n");
|
||||||
wprintw(win, " /join : Join a pending group chat\n");
|
|
||||||
wprintw(win, " /sendfile <path> : Send a file\n");
|
wprintw(win, " /sendfile <path> : Send a file\n");
|
||||||
wprintw(win, " /savefile <id> : Receive a file\n");
|
wprintw(win, " /savefile <id> : Receive a file\n");
|
||||||
wprintw(win, " /cancel <type> <id> : Cancel file transfer where type: in|out\n");
|
wprintw(win, " /cancel <type> <id> : Cancel file transfer where type: in|out\n");
|
||||||
@ -290,7 +270,32 @@ static void help_draw_group(ToxWindow *self)
|
|||||||
wprintw(win, "Group commands:\n");
|
wprintw(win, "Group commands:\n");
|
||||||
wattroff(win, A_BOLD | COLOR_PAIR(RED));
|
wattroff(win, A_BOLD | COLOR_PAIR(RED));
|
||||||
|
|
||||||
wprintw(win, " /title <msg> : Set group title (show current title if no msg)\n\n");
|
wprintw(win, " /chatid : Print the group chat id to share with others\n");
|
||||||
|
wprintw(win, " /mykey : Print your group public key\n");
|
||||||
|
wprintw(win, " /ignore <nick> : Ignore peer\n");
|
||||||
|
wprintw(win, " /unignore <nick> : Unignore peer \n");
|
||||||
|
wprintw(win, " /rejoin : Rejoin the group\n");
|
||||||
|
wprintw(win, " /topic <msg> : Set group topic (show current topic if no msg)\n");
|
||||||
|
wprintw(win, " /whisper <nick> <msg> : Send private message to nick\n");
|
||||||
|
wprintw(win, " /whois <nick> : Display info about nick.\n");
|
||||||
|
|
||||||
|
wattron(win, A_BOLD);
|
||||||
|
wprintw(win, " Moderator commands:\n");
|
||||||
|
wattroff(win, A_BOLD);
|
||||||
|
wprintw(win, " /kick <nick> : Kick peer\n");
|
||||||
|
wprintw(win, " /ban <nick> : Ban peer (leave nick blank to see ban list)\n");
|
||||||
|
wprintw(win, " /unban <Ban ID> : Unban entry\n");
|
||||||
|
wprintw(win, " /silence <nick> : Silences peer for the entire group\n");
|
||||||
|
wprintw(win, " /unsilence <nick> : Unsilences peer\n");
|
||||||
|
|
||||||
|
wattron(win, A_BOLD);
|
||||||
|
wprintw(win, " Founder commands:\n");
|
||||||
|
wattroff(win, A_BOLD);
|
||||||
|
wprintw(win, " /mod <nick> : Promote peer to moderator\n");
|
||||||
|
wprintw(win, " /unmod <nick> : Demote moderator to normal user\n");
|
||||||
|
wprintw(win, " /passwd <password> : Set group password (leave blank to unset)\n");
|
||||||
|
wprintw(win, " /peerlimit <num> : Set group peer limit\n");
|
||||||
|
wprintw(win, " /privacy <state> : Set group privacy state: private|public\n");
|
||||||
|
|
||||||
help_draw_bottom_menu(win);
|
help_draw_bottom_menu(win);
|
||||||
|
|
||||||
@ -298,26 +303,6 @@ static void help_draw_group(ToxWindow *self)
|
|||||||
wrefresh(win);
|
wrefresh(win);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PYTHON
|
|
||||||
static void help_draw_plugin(ToxWindow *self)
|
|
||||||
{
|
|
||||||
WINDOW *win = self->help->win;
|
|
||||||
|
|
||||||
wmove(win, 1, 1);
|
|
||||||
|
|
||||||
wattron(win, A_BOLD | COLOR_PAIR(RED));
|
|
||||||
wprintw(win, "Plugin commands:\n");
|
|
||||||
wattroff(win, A_BOLD | COLOR_PAIR(RED));
|
|
||||||
|
|
||||||
draw_handler_help(win);
|
|
||||||
|
|
||||||
help_draw_bottom_menu(win);
|
|
||||||
|
|
||||||
box(win, ACS_VLINE, ACS_HLINE);
|
|
||||||
wrefresh(win);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void help_draw_contacts(ToxWindow *self)
|
static void help_draw_contacts(ToxWindow *self)
|
||||||
{
|
{
|
||||||
WINDOW *win = self->help->win;
|
WINDOW *win = self->help->win;
|
||||||
@ -342,7 +327,6 @@ static void help_draw_contacts(ToxWindow *self)
|
|||||||
|
|
||||||
void help_onKey(ToxWindow *self, wint_t key)
|
void help_onKey(ToxWindow *self, wint_t key)
|
||||||
{
|
{
|
||||||
int height;
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'x':
|
case 'x':
|
||||||
case T_KEY_ESC:
|
case T_KEY_ESC:
|
||||||
@ -351,9 +335,9 @@ void help_onKey(ToxWindow *self, wint_t key)
|
|||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
#ifdef VIDEO
|
#ifdef VIDEO
|
||||||
help_init_window(self, 22, 80);
|
help_init_window(self, 21, 80);
|
||||||
#elif AUDIO
|
#elif AUDIO
|
||||||
help_init_window(self, 19, 80);
|
help_init_window(self, 18, 80);
|
||||||
#else
|
#else
|
||||||
help_init_window(self, 10, 80);
|
help_init_window(self, 10, 80);
|
||||||
#endif
|
#endif
|
||||||
@ -361,31 +345,21 @@ void help_onKey(ToxWindow *self, wint_t key)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'g':
|
case 'g':
|
||||||
height = 22;
|
|
||||||
#ifdef VIDEO
|
#ifdef VIDEO
|
||||||
height += 8;
|
help_init_window(self, 30, 80);
|
||||||
#elif AUDIO
|
#elif AUDIO
|
||||||
height += 4;
|
help_init_window(self, 26, 80);
|
||||||
|
#else
|
||||||
|
help_init_window(self, 22, 80);
|
||||||
#endif
|
#endif
|
||||||
#ifdef PYTHON
|
|
||||||
height += 2;
|
|
||||||
#endif
|
|
||||||
help_init_window(self, height, 80);
|
|
||||||
self->help->type = HELP_GLOBAL;
|
self->help->type = HELP_GLOBAL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
help_init_window(self, 6, 80);
|
help_init_window(self, 25, 80);
|
||||||
self->help->type = HELP_GROUP;
|
self->help->type = HELP_GROUP;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef PYTHON
|
|
||||||
case 'p':
|
|
||||||
help_init_window(self, 4 + num_registered_handlers(), help_max_width());
|
|
||||||
self->help->type = HELP_PLUGIN;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
help_init_window(self, 10, 80);
|
help_init_window(self, 10, 80);
|
||||||
self->help->type = HELP_CONTACTS;
|
self->help->type = HELP_CONTACTS;
|
||||||
@ -431,11 +405,5 @@ void help_onDraw(ToxWindow *self)
|
|||||||
case HELP_GROUP:
|
case HELP_GROUP:
|
||||||
help_draw_group(self);
|
help_draw_group(self);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef PYTHON
|
|
||||||
case HELP_PLUGIN:
|
|
||||||
help_draw_plugin(self);
|
|
||||||
break;
|
|
||||||
#endif /* PYTHON */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,9 +33,6 @@ typedef enum {
|
|||||||
HELP_GROUP,
|
HELP_GROUP,
|
||||||
HELP_KEYS,
|
HELP_KEYS,
|
||||||
HELP_CONTACTS,
|
HELP_CONTACTS,
|
||||||
#ifdef PYTHON
|
|
||||||
HELP_PLUGIN,
|
|
||||||
#endif
|
|
||||||
} HELP_TYPES;
|
} HELP_TYPES;
|
||||||
|
|
||||||
void help_onDraw(ToxWindow *self);
|
void help_onDraw(ToxWindow *self);
|
||||||
|
@ -171,6 +171,11 @@ void line_info_add(ToxWindow *self, const char *timestr, const char *name1, cons
|
|||||||
len += strlen(user_settings->line_normal) + 3;
|
len += strlen(user_settings->line_normal) + 3;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IN_PRVT_MSG:
|
||||||
|
case OUT_PRVT_MSG:
|
||||||
|
len += strlen(user_settings->line_special) + 3;
|
||||||
|
break;
|
||||||
|
|
||||||
case CONNECTION:
|
case CONNECTION:
|
||||||
len += strlen(user_settings->line_join) + 2;
|
len += strlen(user_settings->line_join) + 2;
|
||||||
break;
|
break;
|
||||||
@ -312,6 +317,8 @@ void line_info_print(ToxWindow *self)
|
|||||||
|
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case IN_MSG:
|
case IN_MSG:
|
||||||
|
case IN_PRVT_MSG:
|
||||||
|
case OUT_PRVT_MSG:
|
||||||
wattron(win, COLOR_PAIR(BLUE));
|
wattron(win, COLOR_PAIR(BLUE));
|
||||||
wprintw(win, "%s ", line->timestr);
|
wprintw(win, "%s ", line->timestr);
|
||||||
wattroff(win, COLOR_PAIR(BLUE));
|
wattroff(win, COLOR_PAIR(BLUE));
|
||||||
@ -324,7 +331,10 @@ void line_info_print(ToxWindow *self)
|
|||||||
nameclr = CYAN;
|
nameclr = CYAN;
|
||||||
|
|
||||||
wattron(win, COLOR_PAIR(nameclr));
|
wattron(win, COLOR_PAIR(nameclr));
|
||||||
wprintw(win, "%s %s: ", user_settings->line_normal, line->name1);
|
wprintw(win, "%s %s: ", (type != OUT_PRVT_MSG && type != IN_PRVT_MSG) ?
|
||||||
|
user_settings->line_normal :
|
||||||
|
user_settings->line_special,
|
||||||
|
line->name1);
|
||||||
wattroff(win, COLOR_PAIR(nameclr));
|
wattroff(win, COLOR_PAIR(nameclr));
|
||||||
|
|
||||||
char *msg = line->msg;
|
char *msg = line->msg;
|
||||||
|
@ -35,10 +35,12 @@ enum {
|
|||||||
SYS_MSG,
|
SYS_MSG,
|
||||||
IN_MSG,
|
IN_MSG,
|
||||||
OUT_MSG,
|
OUT_MSG,
|
||||||
OUT_MSG_READ, /* for sent messages that have received a read reply. don't set this with line_info_add */
|
OUT_MSG_READ, /* for sent messages that have received a read reply. */
|
||||||
IN_ACTION,
|
IN_ACTION,
|
||||||
OUT_ACTION,
|
OUT_ACTION,
|
||||||
OUT_ACTION_READ, /* same as OUT_MSG_READ but for actions */
|
OUT_ACTION_READ, /* same as OUT_MSG_READ but for actions */
|
||||||
|
IN_PRVT_MSG, /* PRVT should only be used for groups */
|
||||||
|
OUT_PRVT_MSG,
|
||||||
PROMPT,
|
PROMPT,
|
||||||
CONNECTION,
|
CONNECTION,
|
||||||
DISCONNECTION,
|
DISCONNECTION,
|
||||||
|
@ -78,7 +78,7 @@ struct tm *get_time(void)
|
|||||||
return timeinfo;
|
return timeinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*Puts the current time in buf in the format of [HH:mm:ss] */
|
/* Puts the current time in buf in the format of [HH:mm:ss] */
|
||||||
void get_time_str(char *buf, int bufsize)
|
void get_time_str(char *buf, int bufsize)
|
||||||
{
|
{
|
||||||
if (user_settings->timestamps == TIMESTAMPS_OFF) {
|
if (user_settings->timestamps == TIMESTAMPS_OFF) {
|
||||||
@ -108,6 +108,24 @@ void get_elapsed_time_str(char *buf, int bufsize, time_t secs)
|
|||||||
snprintf(buf, bufsize, "%ld:%.2ld:%.2ld", hours, minutes, seconds);
|
snprintf(buf, bufsize, "%ld:%.2ld:%.2ld", hours, minutes, seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Converts seconds to string in format H hours, m minutes, s seconds */
|
||||||
|
void get_elapsed_time_str_2(char *buf, int bufsize, uint64_t secs)
|
||||||
|
{
|
||||||
|
if (!secs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
long int seconds = secs % 60;
|
||||||
|
long int minutes = (secs % 3600) / 60;
|
||||||
|
long int hours = secs / 3600;
|
||||||
|
|
||||||
|
if (!minutes && !hours)
|
||||||
|
snprintf(buf, bufsize, "%ld seconds", seconds);
|
||||||
|
else if (!hours)
|
||||||
|
snprintf(buf, bufsize, "%ld minutes, %ld seconds", minutes, seconds);
|
||||||
|
else
|
||||||
|
snprintf(buf, bufsize, "%ld hours, %ld minutes, %ld seconds", hours, minutes, seconds);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Converts a hexidecimal string of length hex_len to binary format and puts the result in output.
|
* Converts a hexidecimal string of length hex_len to binary format and puts the result in output.
|
||||||
* output_size must be exactly half of hex_len.
|
* output_size must be exactly half of hex_len.
|
||||||
@ -323,40 +341,36 @@ void str_to_lower(char *str)
|
|||||||
Returns nick len */
|
Returns nick len */
|
||||||
size_t get_nick_truncate(Tox *m, char *buf, uint32_t friendnum)
|
size_t get_nick_truncate(Tox *m, char *buf, uint32_t friendnum)
|
||||||
{
|
{
|
||||||
TOX_ERR_FRIEND_QUERY err;
|
size_t len = tox_friend_get_name_size(m, friendnum, NULL);
|
||||||
size_t len = tox_friend_get_name_size(m, friendnum, &err);
|
|
||||||
|
|
||||||
if (err != TOX_ERR_FRIEND_QUERY_OK) {
|
if (len == 0) {
|
||||||
goto on_error;
|
strcpy(buf, UNKNOWN_NAME);
|
||||||
|
len = strlen(UNKNOWN_NAME);
|
||||||
} else {
|
} else {
|
||||||
if (!tox_friend_get_name(m, friendnum, (uint8_t *) buf, NULL)) {
|
tox_friend_get_name(m, friendnum, (uint8_t *) buf, NULL);
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1);
|
len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1);
|
||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
filter_str(buf, len);
|
filter_str(buf, len);
|
||||||
return len;
|
return len;
|
||||||
|
|
||||||
on_error:
|
|
||||||
strcpy(buf, UNKNOWN_NAME);
|
|
||||||
len = strlen(UNKNOWN_NAME);
|
|
||||||
buf[len] = '\0';
|
|
||||||
return len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* same as get_nick_truncate but for groupchats */
|
/* same as get_nick_truncate but for groupchats */
|
||||||
int get_group_nick_truncate(Tox *m, char *buf, uint32_t peernum, uint32_t groupnum)
|
int get_group_nick_truncate(Tox *m, char *buf, uint32_t peer_id, int groupnum)
|
||||||
{
|
{
|
||||||
TOX_ERR_CONFERENCE_PEER_QUERY err;
|
TOX_ERR_GROUP_PEER_QUERY err;
|
||||||
size_t len = tox_conference_peer_get_name_size(m, groupnum, peernum, &err);
|
size_t len = tox_group_peer_get_name_size(m, groupnum, peer_id, &err);
|
||||||
|
|
||||||
if (err != TOX_ERR_CONFERENCE_PEER_QUERY_OK) {
|
if (err != TOX_ERR_GROUP_PEER_QUERY_OK) {
|
||||||
goto on_error;
|
strcpy(buf, UNKNOWN_NAME);
|
||||||
|
len = strlen(UNKNOWN_NAME);
|
||||||
} else {
|
} else {
|
||||||
if (!tox_conference_peer_get_name(m, groupnum, peernum, (uint8_t *) buf, NULL)) {
|
tox_group_peer_get_name(m, groupnum, peer_id, (uint8_t *) buf, &err);
|
||||||
goto on_error;
|
|
||||||
|
if (err != TOX_ERR_GROUP_PEER_QUERY_OK) {
|
||||||
|
strcpy(buf, UNKNOWN_NAME);
|
||||||
|
len = strlen(UNKNOWN_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,22 +378,21 @@ int get_group_nick_truncate(Tox *m, char *buf, uint32_t peernum, uint32_t groupn
|
|||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
filter_str(buf, len);
|
filter_str(buf, len);
|
||||||
return len;
|
return len;
|
||||||
|
|
||||||
on_error:
|
|
||||||
strcpy(buf, UNKNOWN_NAME);
|
|
||||||
len = strlen(UNKNOWN_NAME);
|
|
||||||
buf[len] = '\0';
|
|
||||||
return len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copies data to msg buffer.
|
/* copies data to msg buffer.
|
||||||
returns length of msg, which will be no larger than size-1 */
|
returns length of msg.
|
||||||
|
returns 0 and nulls msg if length is too big for buffer size */
|
||||||
size_t copy_tox_str(char *msg, size_t size, const char *data, size_t length)
|
size_t copy_tox_str(char *msg, size_t size, const char *data, size_t length)
|
||||||
{
|
{
|
||||||
size_t len = MIN(length, size - 1);
|
if (length > size - 1) {
|
||||||
memcpy(msg, data, len);
|
msg[0] = '\0';
|
||||||
msg[len] = '\0';
|
return 0;
|
||||||
return len;
|
}
|
||||||
|
|
||||||
|
memcpy(msg, data, length);
|
||||||
|
msg[length] = '\0';
|
||||||
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns index of the first instance of ch in s starting at idx.
|
/* returns index of the first instance of ch in s starting at idx.
|
||||||
|
@ -69,6 +69,9 @@ void get_time_str(char *buf, int bufsize);
|
|||||||
/* Converts seconds to string in format HH:mm:ss; truncates hours and minutes when necessary */
|
/* Converts seconds to string in format HH:mm:ss; truncates hours and minutes when necessary */
|
||||||
void get_elapsed_time_str(char *buf, int bufsize, time_t secs);
|
void get_elapsed_time_str(char *buf, int bufsize, time_t secs);
|
||||||
|
|
||||||
|
/* Converts seconds to string in format H hours, m minutes, s seconds */
|
||||||
|
void get_elapsed_time_str_2(char *buf, int bufsize, uint64_t secs);
|
||||||
|
|
||||||
/* get the current local time (not thread safe) */
|
/* get the current local time (not thread safe) */
|
||||||
struct tm *get_time(void);
|
struct tm *get_time(void);
|
||||||
|
|
||||||
@ -126,10 +129,11 @@ void str_to_lower(char *str);
|
|||||||
size_t get_nick_truncate(Tox *m, char *buf, uint32_t friendnum);
|
size_t get_nick_truncate(Tox *m, char *buf, uint32_t friendnum);
|
||||||
|
|
||||||
/* same as get_nick_truncate but for groupchats */
|
/* same as get_nick_truncate but for groupchats */
|
||||||
int get_group_nick_truncate(Tox *m, char *buf, uint32_t peernum, uint32_t groupnum);
|
int get_group_nick_truncate(Tox *m, char *buf, uint32_t peer_id, int groupnum);
|
||||||
|
|
||||||
/* copies data to msg buffer.
|
/* copies data to msg buffer.
|
||||||
returns length of msg, which will be no larger than size-1 */
|
returns length of msg.
|
||||||
|
returns 0 and nulls msg if length is too big for buffer size */
|
||||||
size_t copy_tox_str(char *msg, size_t size, const char *data, size_t length);
|
size_t copy_tox_str(char *msg, size_t size, const char *data, size_t length);
|
||||||
|
|
||||||
/* returns index of the first instance of ch in s starting at idx.
|
/* returns index of the first instance of ch in s starting at idx.
|
||||||
|
25
src/prompt.c
25
src/prompt.c
@ -49,18 +49,12 @@ extern struct Winthread Winthread;
|
|||||||
|
|
||||||
extern FriendsList Friends;
|
extern FriendsList Friends;
|
||||||
FriendRequests FrndRequests;
|
FriendRequests FrndRequests;
|
||||||
#if defined(PYTHON) && defined(VIDEO)
|
#ifdef VIDEO
|
||||||
#define AC_NUM_GLOB_COMMANDS 23
|
#define AC_NUM_GLOB_COMMANDS 23
|
||||||
#elif defined(PYTHON) && defined(AUDIO)
|
|
||||||
#define AC_NUM_GLOB_COMMANDS 21
|
|
||||||
#elif VIDEO
|
|
||||||
#define AC_NUM_GLOB_COMMANDS 22
|
|
||||||
#elif AUDIO
|
#elif AUDIO
|
||||||
#define AC_NUM_GLOB_COMMANDS 20
|
#define AC_NUM_GLOB_COMMANDS 21
|
||||||
#elif PYTHON
|
|
||||||
#define AC_NUM_GLOB_COMMANDS 19
|
|
||||||
#else
|
#else
|
||||||
#define AC_NUM_GLOB_COMMANDS 18
|
#define AC_NUM_GLOB_COMMANDS 19
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Array of global command names used for tab completion. */
|
/* Array of global command names used for tab completion. */
|
||||||
@ -74,6 +68,7 @@ static const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = {
|
|||||||
{ "/exit" },
|
{ "/exit" },
|
||||||
{ "/group" },
|
{ "/group" },
|
||||||
{ "/help" },
|
{ "/help" },
|
||||||
|
{ "/join" },
|
||||||
{ "/log" },
|
{ "/log" },
|
||||||
{ "/myid" },
|
{ "/myid" },
|
||||||
{ "/myqr" },
|
{ "/myqr" },
|
||||||
@ -98,12 +93,6 @@ static const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = {
|
|||||||
|
|
||||||
#endif /* VIDEO */
|
#endif /* VIDEO */
|
||||||
|
|
||||||
#ifdef PYTHON
|
|
||||||
|
|
||||||
{ "/run" },
|
|
||||||
|
|
||||||
#endif /* PYTHON */
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void kill_prompt_window(ToxWindow *self)
|
void kill_prompt_window(ToxWindow *self)
|
||||||
@ -226,12 +215,6 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
|||||||
|
|
||||||
if (wcsncmp(ctx->line, L"/avatar \"", wcslen(L"/avatar \"")) == 0)
|
if (wcsncmp(ctx->line, L"/avatar \"", wcslen(L"/avatar \"")) == 0)
|
||||||
diff = dir_match(self, m, ctx->line, L"/avatar");
|
diff = dir_match(self, m, ctx->line, L"/avatar");
|
||||||
|
|
||||||
#ifdef PYTHON
|
|
||||||
else if (wcsncmp(ctx->line, L"/run \"", wcslen(L"/run \"")) == 0)
|
|
||||||
diff = dir_match(self, m, ctx->line, L"/run");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
else if (wcsncmp(ctx->line, L"/status ", wcslen(L"/status ")) == 0) {
|
else if (wcsncmp(ctx->line, L"/status ", wcslen(L"/status ")) == 0) {
|
||||||
const char status_cmd_list[3][8] = {
|
const char status_cmd_list[3][8] = {
|
||||||
{"online"},
|
{"online"},
|
||||||
|
345
src/python_api.c
345
src/python_api.c
@ -1,345 +0,0 @@
|
|||||||
/* python_api.c
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Copyright (C) 2017 Jakob Kreuze <jakob@memeware.net>
|
|
||||||
*
|
|
||||||
* This file is part of Toxic.
|
|
||||||
*
|
|
||||||
* Toxic is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Toxic is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Toxic. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <Python.h>
|
|
||||||
|
|
||||||
#include "api.h"
|
|
||||||
#include "execute.h"
|
|
||||||
|
|
||||||
extern Tox *user_tox;
|
|
||||||
|
|
||||||
static struct python_registered_func {
|
|
||||||
char *name;
|
|
||||||
char *help;
|
|
||||||
PyObject *callback;
|
|
||||||
struct python_registered_func *next;
|
|
||||||
} python_commands = {0};
|
|
||||||
|
|
||||||
static PyObject *python_api_display(PyObject *self, PyObject *args)
|
|
||||||
{
|
|
||||||
const char *msg;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "s", &msg))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
api_display(msg);
|
|
||||||
return Py_None;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *python_api_get_nick(PyObject *self, PyObject *args)
|
|
||||||
{
|
|
||||||
char *name;
|
|
||||||
PyObject *ret;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, ""))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
name = api_get_nick();
|
|
||||||
|
|
||||||
if (name == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
ret = Py_BuildValue("s", name);
|
|
||||||
free(name);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *python_api_get_status(PyObject *self, PyObject *args)
|
|
||||||
{
|
|
||||||
PyObject *ret;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, ""))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
switch (api_get_status()) {
|
|
||||||
case TOX_USER_STATUS_NONE:
|
|
||||||
ret = Py_BuildValue("s", "online");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TOX_USER_STATUS_AWAY:
|
|
||||||
ret = Py_BuildValue("s", "away");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TOX_USER_STATUS_BUSY:
|
|
||||||
ret = Py_BuildValue("s", "busy");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *python_api_get_status_message(PyObject *self, PyObject *args)
|
|
||||||
{
|
|
||||||
char *status;
|
|
||||||
PyObject *ret;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, ""))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
status = api_get_status_message();
|
|
||||||
|
|
||||||
if (status == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
ret = Py_BuildValue("s", status);
|
|
||||||
free(status);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *python_api_get_all_friends(PyObject *self, PyObject *args)
|
|
||||||
{
|
|
||||||
size_t i, ii;
|
|
||||||
FriendsList friends;
|
|
||||||
PyObject *cur, *ret;
|
|
||||||
char pubkey_buf[TOX_PUBLIC_KEY_SIZE * 2 + 1];
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, ""))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
friends = api_get_friendslist();
|
|
||||||
ret = PyList_New(0);
|
|
||||||
|
|
||||||
for (i = 0; i < friends.num_friends; i++) {
|
|
||||||
for (ii = 0; ii < TOX_PUBLIC_KEY_SIZE; ii++)
|
|
||||||
snprintf(pubkey_buf + ii * 2, 3, "%02X", friends.list[i].pub_key[ii] & 0xff);
|
|
||||||
|
|
||||||
pubkey_buf[TOX_PUBLIC_KEY_SIZE * 2] = '\0';
|
|
||||||
cur = Py_BuildValue("(s,s)", friends.list[i].name, pubkey_buf);
|
|
||||||
PyList_Append(ret, cur);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *python_api_send(PyObject *self, PyObject *args)
|
|
||||||
{
|
|
||||||
const char *msg;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "s", &msg))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
api_send(msg);
|
|
||||||
return Py_None;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *python_api_execute(PyObject *self, PyObject *args)
|
|
||||||
{
|
|
||||||
int mode;
|
|
||||||
const char *command;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "si", &command, &mode))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
api_execute(command, mode);
|
|
||||||
return Py_None;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *python_api_register(PyObject *self, PyObject *args)
|
|
||||||
{
|
|
||||||
struct python_registered_func *cur;
|
|
||||||
size_t command_len, help_len;
|
|
||||||
const char *command, *help;
|
|
||||||
PyObject *callback;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "ssO:register_command", &command, &help, &callback))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (!PyCallable_Check(callback)) {
|
|
||||||
PyErr_SetString(PyExc_TypeError, "Calback parameter must be callable");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command[0] != '/') {
|
|
||||||
PyErr_SetString(PyExc_TypeError, "Command must be prefixed with a '/'");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (cur = &python_commands; ; cur = cur->next) {
|
|
||||||
if (cur->name != NULL && !strcmp(command, cur->name)) {
|
|
||||||
Py_XDECREF(cur->callback);
|
|
||||||
Py_XINCREF(callback);
|
|
||||||
cur->callback = callback;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cur->next == NULL) {
|
|
||||||
Py_XINCREF(callback);
|
|
||||||
cur->next = malloc(sizeof(struct python_registered_func));
|
|
||||||
|
|
||||||
if (cur->next == NULL)
|
|
||||||
return PyErr_NoMemory();
|
|
||||||
|
|
||||||
command_len = strlen(command);
|
|
||||||
cur->next->name = malloc(command_len + 1);
|
|
||||||
|
|
||||||
if (cur->next->name == NULL)
|
|
||||||
return PyErr_NoMemory();
|
|
||||||
|
|
||||||
strncpy(cur->next->name, command, command_len + 1);
|
|
||||||
help_len = strlen(help);
|
|
||||||
cur->next->help = malloc(help_len + 1);
|
|
||||||
|
|
||||||
if (cur->next->help == NULL)
|
|
||||||
return PyErr_NoMemory();
|
|
||||||
|
|
||||||
strncpy(cur->next->help, help, help_len + 1);
|
|
||||||
cur->next->callback = callback;
|
|
||||||
cur->next->next = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Py_INCREF(Py_None);
|
|
||||||
return Py_None;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyMethodDef ToxicApiMethods[] = {
|
|
||||||
{"display", python_api_display, METH_VARARGS, "Display a message to the current prompt"},
|
|
||||||
{"get_nick", python_api_get_nick, METH_VARARGS, "Return the user's current nickname"},
|
|
||||||
{"get_status", python_api_get_status, METH_VARARGS, "Returns the user's current status"},
|
|
||||||
{"get_status_message", python_api_get_status_message, METH_VARARGS, "Return the user's current status message"},
|
|
||||||
{"get_all_friends", python_api_get_all_friends, METH_VARARGS, "Return all of the user's friends"},
|
|
||||||
{"send", python_api_send, METH_VARARGS, "Send the message to the current user"},
|
|
||||||
{"execute", python_api_execute, METH_VARARGS, "Execute a command like `/nick`"},
|
|
||||||
{"register", python_api_register, METH_VARARGS, "Register a command like `/nick` to a Python function"},
|
|
||||||
{NULL, NULL, 0, NULL},
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct PyModuleDef toxic_api_module = {
|
|
||||||
PyModuleDef_HEAD_INIT,
|
|
||||||
"toxic_api",
|
|
||||||
NULL,
|
|
||||||
-1,
|
|
||||||
ToxicApiMethods
|
|
||||||
};
|
|
||||||
|
|
||||||
PyMODINIT_FUNC PyInit_toxic_api(void)
|
|
||||||
{
|
|
||||||
PyObject *m = PyModule_Create(&toxic_api_module);
|
|
||||||
PyObject *global_command_const = Py_BuildValue("i", GLOBAL_COMMAND_MODE);
|
|
||||||
PyObject *chat_command_const = Py_BuildValue("i", CHAT_COMMAND_MODE);
|
|
||||||
PyObject *groupchat_command_const = Py_BuildValue("i", GROUPCHAT_COMMAND_MODE);
|
|
||||||
PyObject_SetAttrString(m, "GLOBAL_COMMAND", global_command_const);
|
|
||||||
PyObject_SetAttrString(m, "CHAT_COMMAND", chat_command_const);
|
|
||||||
PyObject_SetAttrString(m, "GROUPCHAT_COMMAND", groupchat_command_const);
|
|
||||||
Py_DECREF(global_command_const);
|
|
||||||
Py_DECREF(chat_command_const);
|
|
||||||
Py_DECREF(groupchat_command_const);
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
void terminate_python(void)
|
|
||||||
{
|
|
||||||
struct python_registered_func *cur, *old;
|
|
||||||
|
|
||||||
if (python_commands.name != NULL)
|
|
||||||
free(python_commands.name);
|
|
||||||
|
|
||||||
for (cur = python_commands.next; cur != NULL;) {
|
|
||||||
old = cur;
|
|
||||||
cur = cur->next;
|
|
||||||
free(old->name);
|
|
||||||
free(old);
|
|
||||||
}
|
|
||||||
|
|
||||||
Py_Finalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_python(Tox *m)
|
|
||||||
{
|
|
||||||
user_tox = m;
|
|
||||||
PyImport_AppendInittab("toxic_api", PyInit_toxic_api);
|
|
||||||
Py_Initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void run_python(FILE *fp, char *path)
|
|
||||||
{
|
|
||||||
PyRun_SimpleFile(fp, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
int do_python_command(int num_args, char (*args)[MAX_STR_SIZE])
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
PyObject *callback_args, *args_strings;
|
|
||||||
struct python_registered_func *cur;
|
|
||||||
|
|
||||||
for (cur = &python_commands; cur != NULL; cur = cur->next) {
|
|
||||||
if (cur->name == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!strcmp(args[0], cur->name)) {
|
|
||||||
args_strings = PyList_New(0);
|
|
||||||
|
|
||||||
for (i = 1; i < num_args; i++)
|
|
||||||
PyList_Append(args_strings, Py_BuildValue("s", args[i]));
|
|
||||||
|
|
||||||
callback_args = PyTuple_Pack(1, args_strings);
|
|
||||||
|
|
||||||
if (PyObject_CallObject(cur->callback, callback_args) == NULL)
|
|
||||||
api_display("Exception raised in callback function");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int python_num_registered_handlers(void)
|
|
||||||
{
|
|
||||||
int n = 0;
|
|
||||||
struct python_registered_func *cur;
|
|
||||||
|
|
||||||
for (cur = &python_commands; cur != NULL; cur = cur->next) {
|
|
||||||
if (cur->name != NULL)
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
int python_help_max_width(void)
|
|
||||||
{
|
|
||||||
size_t tmp;
|
|
||||||
int max = 0;
|
|
||||||
struct python_registered_func *cur;
|
|
||||||
|
|
||||||
for (cur = &python_commands; cur != NULL; cur = cur->next) {
|
|
||||||
if (cur->name != NULL) {
|
|
||||||
tmp = strlen(cur->help);
|
|
||||||
max = tmp > max ? tmp : max;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
max = max > 50 ? 50 : max;
|
|
||||||
return 37 + max;
|
|
||||||
}
|
|
||||||
|
|
||||||
void python_draw_handler_help(WINDOW *win)
|
|
||||||
{
|
|
||||||
struct python_registered_func *cur;
|
|
||||||
|
|
||||||
for (cur = &python_commands; cur != NULL; cur = cur->next) {
|
|
||||||
if (cur->name != NULL)
|
|
||||||
wprintw(win, " %-29s: %.50s\n", cur->name, cur->help);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
/* python_api.h
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Copyright (C) 2017 Jakob Kreuze <jakob@memeware.net>
|
|
||||||
*
|
|
||||||
* This file is part of Toxic.
|
|
||||||
*
|
|
||||||
* Toxic is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Toxic is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Toxic. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef PYTHON_API_H
|
|
||||||
#define PYTHON_API_H
|
|
||||||
|
|
||||||
#include <Python.h>
|
|
||||||
|
|
||||||
PyMODINIT_FUNC PyInit_toxic_api(void);
|
|
||||||
void terminate_python(void);
|
|
||||||
void init_python(Tox *m);
|
|
||||||
void run_python(FILE *fp, char *path);
|
|
||||||
int do_python_command(int num_args, char (*args)[MAX_STR_SIZE]);
|
|
||||||
int python_num_registered_handlers(void);
|
|
||||||
int python_help_max_width(void);
|
|
||||||
void python_draw_handler_help(WINDOW *win);
|
|
||||||
|
|
||||||
#endif /* #define PYTHON_API_H */
|
|
@ -23,7 +23,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <qrencode.h>
|
#include <qrencode.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "toxic.h"
|
#include "toxic.h"
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
|
@ -68,6 +68,7 @@ static struct ui_strings {
|
|||||||
const char *line_quit;
|
const char *line_quit;
|
||||||
const char *line_alert;
|
const char *line_alert;
|
||||||
const char *line_normal;
|
const char *line_normal;
|
||||||
|
const char *line_special;
|
||||||
|
|
||||||
const char *mplex_away;
|
const char *mplex_away;
|
||||||
const char *mplex_away_note;
|
const char *mplex_away_note;
|
||||||
@ -94,6 +95,7 @@ static struct ui_strings {
|
|||||||
"line_quit",
|
"line_quit",
|
||||||
"line_alert",
|
"line_alert",
|
||||||
"line_normal",
|
"line_normal",
|
||||||
|
"line_special",
|
||||||
"mplex_away",
|
"mplex_away",
|
||||||
"mplex_away_note",
|
"mplex_away_note",
|
||||||
};
|
};
|
||||||
@ -122,6 +124,7 @@ static void ui_defaults(struct user_settings *settings)
|
|||||||
snprintf(settings->line_quit, LINE_HINT_MAX + 1, "%s", LINE_QUIT);
|
snprintf(settings->line_quit, LINE_HINT_MAX + 1, "%s", LINE_QUIT);
|
||||||
snprintf(settings->line_alert, LINE_HINT_MAX + 1, "%s", LINE_ALERT);
|
snprintf(settings->line_alert, LINE_HINT_MAX + 1, "%s", LINE_ALERT);
|
||||||
snprintf(settings->line_normal, LINE_HINT_MAX + 1, "%s", LINE_NORMAL);
|
snprintf(settings->line_normal, LINE_HINT_MAX + 1, "%s", LINE_NORMAL);
|
||||||
|
snprintf(settings->line_special, LINE_HINT_MAX + 1, "%s", LINE_SPECIAL);
|
||||||
|
|
||||||
settings->mplex_away = MPLEX_ON;
|
settings->mplex_away = MPLEX_ON;
|
||||||
snprintf (settings->mplex_away_note,
|
snprintf (settings->mplex_away_note,
|
||||||
@ -179,14 +182,12 @@ static const struct tox_strings {
|
|||||||
const char *download_path;
|
const char *download_path;
|
||||||
const char *chatlogs_path;
|
const char *chatlogs_path;
|
||||||
const char *avatar_path;
|
const char *avatar_path;
|
||||||
const char *autorun_path;
|
|
||||||
const char *password_eval;
|
const char *password_eval;
|
||||||
} tox_strings = {
|
} tox_strings = {
|
||||||
"tox",
|
"tox",
|
||||||
"download_path",
|
"download_path",
|
||||||
"chatlogs_path",
|
"chatlogs_path",
|
||||||
"avatar_path",
|
"avatar_path",
|
||||||
"autorun_path",
|
|
||||||
"password_eval",
|
"password_eval",
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -195,7 +196,6 @@ static void tox_defaults(struct user_settings *settings)
|
|||||||
strcpy(settings->download_path, "");
|
strcpy(settings->download_path, "");
|
||||||
strcpy(settings->chatlogs_path, "");
|
strcpy(settings->chatlogs_path, "");
|
||||||
strcpy(settings->avatar_path, "");
|
strcpy(settings->avatar_path, "");
|
||||||
strcpy(settings->autorun_path, "");
|
|
||||||
strcpy(settings->password_eval, "");
|
strcpy(settings->password_eval, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,6 +383,10 @@ int settings_load(struct user_settings *s, const char *patharg)
|
|||||||
snprintf(s->line_normal, sizeof(s->line_normal), "%s", str);
|
snprintf(s->line_normal, sizeof(s->line_normal), "%s", str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( config_setting_lookup_string(setting, ui_strings.line_special, &str) ) {
|
||||||
|
snprintf(s->line_special, sizeof(s->line_special), "%s", str);
|
||||||
|
}
|
||||||
|
|
||||||
config_setting_lookup_bool (setting, ui_strings.mplex_away, &s->mplex_away);
|
config_setting_lookup_bool (setting, ui_strings.mplex_away, &s->mplex_away);
|
||||||
|
|
||||||
if (config_setting_lookup_string (setting, ui_strings.mplex_away_note, &str)) {
|
if (config_setting_lookup_string (setting, ui_strings.mplex_away_note, &str)) {
|
||||||
@ -421,20 +425,6 @@ int settings_load(struct user_settings *s, const char *patharg)
|
|||||||
s->avatar_path[0] = '\0';
|
s->avatar_path[0] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PYTHON
|
|
||||||
|
|
||||||
if ( config_setting_lookup_string(setting, tox_strings.autorun_path, &str) ) {
|
|
||||||
snprintf(s->autorun_path, sizeof(s->autorun_path), "%s", str);
|
|
||||||
int len = strlen(str);
|
|
||||||
|
|
||||||
if (len >= sizeof(s->autorun_path) - 2)
|
|
||||||
s->autorun_path[0] = '\0';
|
|
||||||
else if (s->autorun_path[len - 1] != '/')
|
|
||||||
strcat(&s->autorun_path[len - 1], "/");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ( config_setting_lookup_string(setting, tox_strings.password_eval, &str) ) {
|
if ( config_setting_lookup_string(setting, tox_strings.password_eval, &str) ) {
|
||||||
snprintf(s->password_eval, sizeof(s->password_eval), "%s", str);
|
snprintf(s->password_eval, sizeof(s->password_eval), "%s", str);
|
||||||
int len = strlen(str);
|
int len = strlen(str);
|
||||||
|
@ -59,11 +59,11 @@ struct user_settings {
|
|||||||
char line_quit[LINE_HINT_MAX + 1];
|
char line_quit[LINE_HINT_MAX + 1];
|
||||||
char line_alert[LINE_HINT_MAX + 1];
|
char line_alert[LINE_HINT_MAX + 1];
|
||||||
char line_normal[LINE_HINT_MAX + 1];
|
char line_normal[LINE_HINT_MAX + 1];
|
||||||
|
char line_special[LINE_HINT_MAX + 1];
|
||||||
|
|
||||||
char download_path[PATH_MAX];
|
char download_path[PATH_MAX];
|
||||||
char chatlogs_path[PATH_MAX];
|
char chatlogs_path[PATH_MAX];
|
||||||
char avatar_path[PATH_MAX];
|
char avatar_path[PATH_MAX];
|
||||||
char autorun_path[PATH_MAX];
|
|
||||||
char password_eval[PASSWORD_EVAL_MAX];
|
char password_eval[PASSWORD_EVAL_MAX];
|
||||||
|
|
||||||
int key_next_tab;
|
int key_next_tab;
|
||||||
@ -120,6 +120,7 @@ enum {
|
|||||||
#define LINE_QUIT "<--"
|
#define LINE_QUIT "<--"
|
||||||
#define LINE_ALERT "-!-"
|
#define LINE_ALERT "-!-"
|
||||||
#define LINE_NORMAL "---"
|
#define LINE_NORMAL "---"
|
||||||
|
#define LINE_SPECIAL ">>>"
|
||||||
#define TIMESTAMP_DEFAULT "%H:%M:%S"
|
#define TIMESTAMP_DEFAULT "%H:%M:%S"
|
||||||
#define LOG_TIMESTAMP_DEFAULT "%Y/%m/%d [%H:%M:%S]"
|
#define LOG_TIMESTAMP_DEFAULT "%Y/%m/%d [%H:%M:%S]"
|
||||||
#define MPLEX_AWAY_NOTE "Detached from screen"
|
#define MPLEX_AWAY_NOTE "Detached from screen"
|
||||||
|
100
src/toxic.c
100
src/toxic.c
@ -49,6 +49,7 @@
|
|||||||
#include "toxic.h"
|
#include "toxic.h"
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
#include "friendlist.h"
|
#include "friendlist.h"
|
||||||
|
#include "groupchat.h"
|
||||||
#include "prompt.h"
|
#include "prompt.h"
|
||||||
#include "misc_tools.h"
|
#include "misc_tools.h"
|
||||||
#include "file_transfers.h"
|
#include "file_transfers.h"
|
||||||
@ -75,11 +76,6 @@
|
|||||||
ToxAV *av;
|
ToxAV *av;
|
||||||
#endif /* AUDIO */
|
#endif /* AUDIO */
|
||||||
|
|
||||||
#ifdef PYTHON
|
|
||||||
#include "api.h"
|
|
||||||
#include "python_api.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PACKAGE_DATADIR
|
#ifndef PACKAGE_DATADIR
|
||||||
#define PACKAGE_DATADIR "."
|
#define PACKAGE_DATADIR "."
|
||||||
#endif
|
#endif
|
||||||
@ -109,16 +105,9 @@ static struct user_password {
|
|||||||
int len;
|
int len;
|
||||||
} user_password;
|
} user_password;
|
||||||
|
|
||||||
static time_t last_signal_time;
|
|
||||||
|
|
||||||
static void catch_SIGINT(int sig)
|
static void catch_SIGINT(int sig)
|
||||||
{
|
{
|
||||||
time_t cur_time = get_unix_time();
|
Winthread.sig_exit_toxic = 1;
|
||||||
if (difftime(cur_time, last_signal_time) <= 1) {
|
|
||||||
Winthread.sig_exit_toxic = 1;
|
|
||||||
} else {
|
|
||||||
last_signal_time = cur_time;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void catch_SIGSEGV(int sig)
|
static void catch_SIGSEGV(int sig)
|
||||||
@ -174,10 +163,6 @@ void exit_toxic_success(Tox *m)
|
|||||||
terminate_audio();
|
terminate_audio();
|
||||||
#endif /* AUDIO */
|
#endif /* AUDIO */
|
||||||
|
|
||||||
#ifdef PYTHON
|
|
||||||
terminate_python();
|
|
||||||
#endif /* PYTHON */
|
|
||||||
|
|
||||||
free_global_data();
|
free_global_data();
|
||||||
tox_kill(m);
|
tox_kill(m);
|
||||||
endwin();
|
endwin();
|
||||||
@ -298,6 +283,17 @@ static void print_init_messages(ToxWindow *toxwin)
|
|||||||
line_info_add(toxwin, NULL, NULL, NULL, SYS_MSG, 0, 0, init_messages.msgs[i]);
|
line_info_add(toxwin, NULL, NULL, NULL, SYS_MSG, 0, 0, init_messages.msgs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void load_groups(Tox *m)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
size_t numgroups = tox_group_get_number_groups(m);
|
||||||
|
|
||||||
|
for (i = 0; i < numgroups; ++i) {
|
||||||
|
if (init_groupchat_win(m, i, NULL, 0) == -1)
|
||||||
|
tox_group_leave(m, i, NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void load_friendlist(Tox *m)
|
static void load_friendlist(Tox *m)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -398,7 +394,6 @@ static void first_time_encrypt(const char *msg)
|
|||||||
do {
|
do {
|
||||||
system("clear");
|
system("clear");
|
||||||
printf("%s ", msg);
|
printf("%s ", msg);
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
if (!strcasecmp(ch, "y\n") || !strcasecmp(ch, "n\n") || !strcasecmp(ch, "yes\n")
|
if (!strcasecmp(ch, "y\n") || !strcasecmp(ch, "n\n") || !strcasecmp(ch, "yes\n")
|
||||||
|| !strcasecmp(ch, "no\n") || !strcasecmp(ch, "q\n"))
|
|| !strcasecmp(ch, "no\n") || !strcasecmp(ch, "q\n"))
|
||||||
@ -419,7 +414,6 @@ static void first_time_encrypt(const char *msg)
|
|||||||
printf("Enter a new password (must be at least %d characters) ", MIN_PASSWORD_LEN);
|
printf("Enter a new password (must be at least %d characters) ", MIN_PASSWORD_LEN);
|
||||||
|
|
||||||
while (valid_password == false) {
|
while (valid_password == false) {
|
||||||
fflush(stdout); // Flush all before user input
|
|
||||||
len = password_prompt(user_password.pass, sizeof(user_password.pass));
|
len = password_prompt(user_password.pass, sizeof(user_password.pass));
|
||||||
user_password.len = len;
|
user_password.len = len;
|
||||||
|
|
||||||
@ -538,23 +532,33 @@ int store_data(Tox *m, const char *path)
|
|||||||
|
|
||||||
static void init_tox_callbacks(Tox *m)
|
static void init_tox_callbacks(Tox *m)
|
||||||
{
|
{
|
||||||
tox_callback_self_connection_status(m, prompt_onSelfConnectionChange);
|
tox_callback_self_connection_status(m, prompt_onSelfConnectionChange, NULL);
|
||||||
tox_callback_friend_connection_status(m, on_connectionchange);
|
tox_callback_friend_connection_status(m, on_connectionchange, NULL);
|
||||||
tox_callback_friend_typing(m, on_typing_change);
|
tox_callback_friend_typing(m, on_typing_change, NULL);
|
||||||
tox_callback_friend_request(m, on_request);
|
tox_callback_friend_request(m, on_request, NULL);
|
||||||
tox_callback_friend_message(m, on_message);
|
tox_callback_friend_message(m, on_message, NULL);
|
||||||
tox_callback_friend_name(m, on_nickchange);
|
tox_callback_friend_name(m, on_nickchange, NULL);
|
||||||
tox_callback_friend_status(m, on_statuschange);
|
tox_callback_friend_status(m, on_statuschange, NULL);
|
||||||
tox_callback_friend_status_message(m, on_statusmessagechange);
|
tox_callback_friend_status_message(m, on_statusmessagechange, NULL);
|
||||||
tox_callback_friend_read_receipt(m, on_read_receipt);
|
tox_callback_friend_read_receipt(m, on_read_receipt, NULL);
|
||||||
tox_callback_conference_invite(m, on_groupinvite);
|
tox_callback_file_recv(m, on_file_recv, NULL);
|
||||||
tox_callback_conference_message(m, on_groupmessage);
|
tox_callback_file_chunk_request(m, on_file_chunk_request, NULL);
|
||||||
tox_callback_conference_namelist_change(m, on_group_namelistchange);
|
tox_callback_file_recv_control(m, on_file_control, NULL);
|
||||||
tox_callback_conference_title(m, on_group_titlechange);
|
tox_callback_file_recv_chunk(m, on_file_recv_chunk, NULL);
|
||||||
tox_callback_file_recv(m, on_file_recv);
|
tox_callback_group_invite(m, on_group_invite, NULL);
|
||||||
tox_callback_file_chunk_request(m, on_file_chunk_request);
|
tox_callback_group_message(m, on_group_message, NULL);
|
||||||
tox_callback_file_recv_control(m, on_file_control);
|
tox_callback_group_private_message(m, on_group_private_message, NULL);
|
||||||
tox_callback_file_recv_chunk(m, on_file_recv_chunk);
|
tox_callback_group_peer_join(m, on_group_peer_join, NULL);
|
||||||
|
tox_callback_group_peer_exit(m, on_group_peer_exit, NULL);
|
||||||
|
tox_callback_group_peer_name(m, on_group_nick_change, NULL);
|
||||||
|
tox_callback_group_peer_status(m, on_group_status_change, NULL);
|
||||||
|
tox_callback_group_topic(m, on_group_topic_change, NULL);
|
||||||
|
tox_callback_group_peer_limit(m, on_group_peer_limit, NULL);
|
||||||
|
tox_callback_group_privacy_state(m, on_group_privacy_state, NULL);
|
||||||
|
tox_callback_group_password(m, on_group_password, NULL);
|
||||||
|
tox_callback_group_self_join(m, on_group_self_join, NULL);
|
||||||
|
tox_callback_group_join_fail(m, on_group_rejected, NULL);
|
||||||
|
tox_callback_group_moderation(m, on_group_moderation, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_tox_options(struct Tox_Options *tox_opts)
|
static void init_tox_options(struct Tox_Options *tox_opts)
|
||||||
@ -645,7 +649,6 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, TOX_ERR_NEW
|
|||||||
char plain[plain_len];
|
char plain[plain_len];
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
fflush(stdout); // Flush before prompts so the user sees the question/message
|
|
||||||
if (pweval) {
|
if (pweval) {
|
||||||
pwlen = password_eval(user_password.pass, sizeof(user_password.pass));
|
pwlen = password_eval(user_password.pass, sizeof(user_password.pass));
|
||||||
} else {
|
} else {
|
||||||
@ -765,7 +768,7 @@ static void do_toxic(Tox *m)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tox_iterate(m, NULL);
|
tox_iterate(m);
|
||||||
do_tox_connection(m);
|
do_tox_connection(m);
|
||||||
pthread_mutex_unlock(&Winthread.lock);
|
pthread_mutex_unlock(&Winthread.lock);
|
||||||
}
|
}
|
||||||
@ -854,13 +857,6 @@ static void print_usage(void)
|
|||||||
fprintf(stderr, " -t, --force-tcp Force toxic to use a TCP connection (use with proxies)\n");
|
fprintf(stderr, " -t, --force-tcp Force toxic to use a TCP connection (use with proxies)\n");
|
||||||
fprintf(stderr, " -T, --tcp-server Act as a TCP relay server: Requires [port]\n");
|
fprintf(stderr, " -T, --tcp-server Act as a TCP relay server: Requires [port]\n");
|
||||||
fprintf(stderr, " -u, --unencrypt-data Unencrypt an encrypted data file\n");
|
fprintf(stderr, " -u, --unencrypt-data Unencrypt an encrypted data file\n");
|
||||||
fprintf(stderr, " -v, --version Print the version\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_version(void)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Toxic version %s\n", TOXICVER);
|
|
||||||
fprintf(stderr, "Toxcore version %d.%d.%d\n", tox_version_major(), tox_version_minor(), tox_version_patch());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_default_opts(void)
|
static void set_default_opts(void)
|
||||||
@ -891,11 +887,10 @@ static void parse_args(int argc, char *argv[])
|
|||||||
{"SOCKS5-proxy", required_argument, 0, 'p'},
|
{"SOCKS5-proxy", required_argument, 0, 'p'},
|
||||||
{"HTTP-proxy", required_argument, 0, 'P'},
|
{"HTTP-proxy", required_argument, 0, 'P'},
|
||||||
{"unencrypt-data", no_argument, 0, 'u'},
|
{"unencrypt-data", no_argument, 0, 'u'},
|
||||||
{"version", no_argument, 0, 'v'},
|
|
||||||
{NULL, no_argument, NULL, 0},
|
{NULL, no_argument, NULL, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *opts_str = "4bdehotuxvc:f:n:r:p:P:T:";
|
const char *opts_str = "4bdehotuxc:f:n:r:p:P:T:";
|
||||||
int opt, indexptr;
|
int opt, indexptr;
|
||||||
long int port = 0;
|
long int port = 0;
|
||||||
|
|
||||||
@ -1018,9 +1013,6 @@ static void parse_args(int argc, char *argv[])
|
|||||||
arg_opts.unencrypt_data = 1;
|
arg_opts.unencrypt_data = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'v':
|
|
||||||
print_version();
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
case 'h':
|
case 'h':
|
||||||
default:
|
default:
|
||||||
print_usage();
|
print_usage();
|
||||||
@ -1227,13 +1219,6 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
#endif /* AUDIO */
|
#endif /* AUDIO */
|
||||||
|
|
||||||
#ifdef PYTHON
|
|
||||||
|
|
||||||
init_python(m);
|
|
||||||
invoke_autoruns(prompt->chatwin->history, prompt);
|
|
||||||
|
|
||||||
#endif /* PYTHON */
|
|
||||||
|
|
||||||
init_notify(60, 3000);
|
init_notify(60, 3000);
|
||||||
|
|
||||||
/* screen/tmux auto-away timer */
|
/* screen/tmux auto-away timer */
|
||||||
@ -1247,6 +1232,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&Winthread.lock);
|
pthread_mutex_lock(&Winthread.lock);
|
||||||
|
load_groups(m);
|
||||||
print_init_messages(prompt);
|
print_init_messages(prompt);
|
||||||
pthread_mutex_unlock(&Winthread.lock);
|
pthread_mutex_unlock(&Winthread.lock);
|
||||||
|
|
||||||
|
32
src/toxic.h
32
src/toxic.h
@ -114,13 +114,11 @@ void on_nickchange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t
|
|||||||
void on_statuschange(Tox *m, uint32_t friendnumber, TOX_USER_STATUS status, void *userdata);
|
void on_statuschange(Tox *m, uint32_t friendnumber, TOX_USER_STATUS status, void *userdata);
|
||||||
void on_statusmessagechange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata);
|
void on_statusmessagechange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata);
|
||||||
void on_friendadded(Tox *m, uint32_t friendnumber, bool sort);
|
void on_friendadded(Tox *m, uint32_t friendnumber, bool sort);
|
||||||
void on_groupmessage(Tox *m, uint32_t groupnumber, uint32_t peernumber, TOX_MESSAGE_TYPE type,
|
void on_file_chunk_request(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length,
|
||||||
const uint8_t *message, size_t length, void *userdata);
|
void *userdata);
|
||||||
void on_groupinvite(Tox *m, uint32_t friendnumber, TOX_CONFERENCE_TYPE type, const uint8_t *group_pub_key,
|
void on_groupinvite(Tox *m, int32_t friendnumber, uint8_t type, const uint8_t *group_pub_key, uint16_t length,
|
||||||
size_t length, void *userdata);
|
void *userdata);
|
||||||
void on_group_namelistchange(Tox *m, uint32_t groupnumber, uint32_t peernumber, TOX_CONFERENCE_STATE_CHANGE change,
|
void on_group_titlechange(Tox *m, int groupnumber, int peernumber, const uint8_t *title, uint8_t length,
|
||||||
void *userdata);
|
|
||||||
void on_group_titlechange(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *title, size_t length,
|
|
||||||
void *userdata);
|
void *userdata);
|
||||||
void on_file_chunk_request(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length,
|
void on_file_chunk_request(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length,
|
||||||
void *userdata);
|
void *userdata);
|
||||||
@ -131,5 +129,25 @@ void on_file_recv(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint32_t k
|
|||||||
const uint8_t *filename, size_t filename_length, void *userdata);
|
const uint8_t *filename, size_t filename_length, void *userdata);
|
||||||
void on_typing_change(Tox *m, uint32_t friendnumber, bool is_typing, void *userdata);
|
void on_typing_change(Tox *m, uint32_t friendnumber, bool is_typing, void *userdata);
|
||||||
void on_read_receipt(Tox *m, uint32_t friendnumber, uint32_t receipt, void *userdata);
|
void on_read_receipt(Tox *m, uint32_t friendnumber, uint32_t receipt, void *userdata);
|
||||||
|
void on_group_invite(Tox *m, uint32_t friendnumber, const uint8_t *invite_data, size_t length, void *userdata);
|
||||||
|
void on_group_message(Tox *m, uint32_t groupnumber, uint32_t peernumber, TOX_MESSAGE_TYPE type,
|
||||||
|
const uint8_t *message, size_t length, void *userdata);
|
||||||
|
void on_group_private_message(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *message, size_t length,
|
||||||
|
void *userdata);
|
||||||
|
void on_group_peer_join(Tox *m, uint32_t groupnumber, uint32_t peernumber, void *userdata);
|
||||||
|
void on_group_peer_exit(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *partmsg, size_t length,
|
||||||
|
void *userdata);
|
||||||
|
void on_group_topic_change(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *topic, size_t length,
|
||||||
|
void *userdata);
|
||||||
|
void on_group_peer_limit(Tox *m, uint32_t groupnumber, uint32_t peer_limit, void *userdata);
|
||||||
|
void on_group_privacy_state(Tox *m, uint32_t groupnumber, TOX_GROUP_PRIVACY_STATE privacy_state, void *userdata);
|
||||||
|
void on_group_password(Tox *m, uint32_t groupnumber, const uint8_t *password, size_t length, void *userdata);
|
||||||
|
void on_group_nick_change(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *newname, size_t length,
|
||||||
|
void *userdata);
|
||||||
|
void on_group_status_change(Tox *m, uint32_t groupnumber, uint32_t peernumber, TOX_USER_STATUS status, void *userdata);
|
||||||
|
void on_group_self_join(Tox *m, uint32_t groupnumber, void *userdata);
|
||||||
|
void on_group_rejected(Tox *m, uint32_t groupnumber, TOX_GROUP_JOIN_FAIL type, void *userdata);
|
||||||
|
void on_group_moderation(Tox *m, uint32_t groupnumber, uint32_t source_peernum, uint32_t target_peernum,
|
||||||
|
TOX_GROUP_MOD_EVENT type, void *userdata);
|
||||||
|
|
||||||
#endif /* #define TOXIC_H */
|
#endif /* #define TOXIC_H */
|
||||||
|
163
src/windows.c
163
src/windows.c
@ -151,8 +151,18 @@ void on_friendadded(Tox *m, uint32_t friendnumber, bool sort)
|
|||||||
store_data(m, DATA_FILE);
|
store_data(m, DATA_FILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_groupmessage(Tox *m, uint32_t groupnumber, uint32_t peernumber, TOX_MESSAGE_TYPE type,
|
void on_group_invite(Tox *m, uint32_t friendnumber, const uint8_t *invite_data, size_t length, void *userdata)
|
||||||
const uint8_t *message, size_t length, void *userdata)
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||||
|
if (windows[i].onGroupInvite != NULL)
|
||||||
|
windows[i].onGroupInvite(&windows[i], m, friendnumber, (char *) invite_data, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_group_message(Tox *m, uint32_t groupnumber, uint32_t peer_id, TOX_MESSAGE_TYPE type,
|
||||||
|
const uint8_t *message, size_t length, void *userdata)
|
||||||
{
|
{
|
||||||
char msg[MAX_STR_SIZE + 1];
|
char msg[MAX_STR_SIZE + 1];
|
||||||
length = copy_tox_str(msg, sizeof(msg), (const char *) message, length);
|
length = copy_tox_str(msg, sizeof(msg), (const char *) message, length);
|
||||||
@ -161,43 +171,151 @@ void on_groupmessage(Tox *m, uint32_t groupnumber, uint32_t peernumber, TOX_MESS
|
|||||||
|
|
||||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||||
if (windows[i].onGroupMessage != NULL)
|
if (windows[i].onGroupMessage != NULL)
|
||||||
windows[i].onGroupMessage(&windows[i], m, groupnumber, peernumber, type, msg, length);
|
windows[i].onGroupMessage(&windows[i], m, groupnumber, peer_id, type, msg, length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_groupinvite(Tox *m, uint32_t friendnumber, TOX_CONFERENCE_TYPE type, const uint8_t *group_pub_key,
|
void on_group_private_message(Tox *m, uint32_t groupnumber, uint32_t peer_id, const uint8_t *message,
|
||||||
size_t length, void *userdata)
|
size_t length, void *userdata)
|
||||||
|
{
|
||||||
|
char msg[MAX_STR_SIZE + 1];
|
||||||
|
length = copy_tox_str(msg, sizeof(msg), (const char *) message, length);
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||||
|
if (windows[i].onGroupPrivateMessage != NULL)
|
||||||
|
windows[i].onGroupPrivateMessage(&windows[i], m, groupnumber, peer_id, msg, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_group_status_change(Tox *m, uint32_t groupnumber, uint32_t peer_id, TOX_USER_STATUS status, void *userdata)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||||
if (windows[i].onGroupInvite != NULL)
|
if (windows[i].onGroupStatusChange != NULL)
|
||||||
windows[i].onGroupInvite(&windows[i], m, friendnumber, type, (char *) group_pub_key, length);
|
windows[i].onGroupStatusChange(&windows[i], m, groupnumber, peer_id, status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_group_namelistchange(Tox *m, uint32_t groupnumber, uint32_t peernumber, TOX_CONFERENCE_STATE_CHANGE change,
|
void on_group_peer_join(Tox *m, uint32_t groupnumber, uint32_t peer_id, void *userdata)
|
||||||
void *userdata)
|
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||||
if (windows[i].onGroupNamelistChange != NULL)
|
if (windows[i].onGroupPeerJoin != NULL)
|
||||||
windows[i].onGroupNamelistChange(&windows[i], m, groupnumber, peernumber, change);
|
windows[i].onGroupPeerJoin(&windows[i], m, groupnumber, peer_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_group_titlechange(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *title, size_t length,
|
void on_group_peer_exit(Tox *m, uint32_t groupnumber, uint32_t peer_id, const uint8_t *partmsg, size_t length,
|
||||||
void *userdata)
|
void *userdata)
|
||||||
|
{
|
||||||
|
char msg[MAX_STR_SIZE + 1];
|
||||||
|
|
||||||
|
if (length == 0 || !partmsg) {
|
||||||
|
strcpy(msg, "Quit");
|
||||||
|
length = strlen(msg);
|
||||||
|
} else {
|
||||||
|
length = copy_tox_str(msg, sizeof(msg), (const char *) partmsg, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||||
|
if (windows[i].onGroupPeerExit != NULL)
|
||||||
|
windows[i].onGroupPeerExit(&windows[i], m, groupnumber, peer_id, msg, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_group_topic_change(Tox *m, uint32_t groupnumber, uint32_t peer_id, const uint8_t *topic, size_t length,
|
||||||
|
void *userdata)
|
||||||
{
|
{
|
||||||
char data[MAX_STR_SIZE + 1];
|
char data[MAX_STR_SIZE + 1];
|
||||||
length = copy_tox_str(data, sizeof(data), (const char *) title, length);
|
length = copy_tox_str(data, sizeof(data), (const char *) topic, length);
|
||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||||
if (windows[i].onGroupTitleChange != NULL)
|
if (windows[i].onGroupTopicChange != NULL)
|
||||||
windows[i].onGroupTitleChange(&windows[i], m, groupnumber, peernumber, data, length);
|
windows[i].onGroupTopicChange(&windows[i], m, groupnumber, peer_id, data, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_group_peer_limit(Tox *m, uint32_t groupnumber, uint32_t peer_limit, void *userdata)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||||
|
if (windows[i].onGroupPeerLimit != NULL)
|
||||||
|
windows[i].onGroupPeerLimit(&windows[i], m, groupnumber, peer_limit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_group_privacy_state(Tox *m, uint32_t groupnumber, TOX_GROUP_PRIVACY_STATE privacy_state, void *userdata)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||||
|
if (windows[i].onGroupPrivacyState != NULL)
|
||||||
|
windows[i].onGroupPrivacyState(&windows[i], m, groupnumber, privacy_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_group_password(Tox *m, uint32_t groupnumber, const uint8_t *password, size_t length, void *userdata)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||||
|
if (windows[i].onGroupPassword != NULL)
|
||||||
|
windows[i].onGroupPassword(&windows[i], m, groupnumber, (char *) password, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_group_nick_change(Tox *m, uint32_t groupnumber, uint32_t peer_id, const uint8_t *newname, size_t length,
|
||||||
|
void *userdata)
|
||||||
|
{
|
||||||
|
char name[TOXIC_MAX_NAME_LENGTH + 1];
|
||||||
|
length = copy_tox_str(name, sizeof(name), (const char *) newname, length);
|
||||||
|
filter_str(name, length);
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||||
|
if (windows[i].onGroupNickChange != NULL)
|
||||||
|
windows[i].onGroupNickChange(&windows[i], m, groupnumber, peer_id, name, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_group_self_join(Tox *m, uint32_t groupnumber, void *userdata)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||||
|
if (windows[i].onGroupSelfJoin != NULL)
|
||||||
|
windows[i].onGroupSelfJoin(&windows[i], m, groupnumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_group_rejected(Tox *m, uint32_t groupnumber, TOX_GROUP_JOIN_FAIL type, void *userdata)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||||
|
if (windows[i].onGroupRejected != NULL)
|
||||||
|
windows[i].onGroupRejected(&windows[i], m, groupnumber, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_group_moderation(Tox *m, uint32_t groupnumber, uint32_t source_peer_id, uint32_t target_peer_id,
|
||||||
|
TOX_GROUP_MOD_EVENT type, void *userdata)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||||
|
if (windows[i].onGroupModeration != NULL)
|
||||||
|
windows[i].onGroupModeration(&windows[i], m, groupnumber, source_peer_id, target_peer_id, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,6 +593,10 @@ static void draw_bar(void)
|
|||||||
|
|
||||||
move(LINES - 1, 0);
|
move(LINES - 1, 0);
|
||||||
|
|
||||||
|
attron(COLOR_PAIR(BLUE) | A_BOLD);
|
||||||
|
printw(" TOXIC " TOXICVER " |");
|
||||||
|
attroff(COLOR_PAIR(BLUE) | A_BOLD);
|
||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||||
@ -510,9 +632,8 @@ static void draw_bar(void)
|
|||||||
|
|
||||||
void draw_active_window(Tox *m)
|
void draw_active_window(Tox *m)
|
||||||
{
|
{
|
||||||
ToxWindow *a = active_window;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&Winthread.lock);
|
pthread_mutex_lock(&Winthread.lock);
|
||||||
|
ToxWindow *a = active_window;
|
||||||
a->alert = WINDOW_ALERT_NONE;
|
a->alert = WINDOW_ALERT_NONE;
|
||||||
pthread_mutex_unlock(&Winthread.lock);
|
pthread_mutex_unlock(&Winthread.lock);
|
||||||
|
|
||||||
@ -584,12 +705,6 @@ ToxWindow *get_window_ptr(int i)
|
|||||||
return toxwin;
|
return toxwin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns a pointer to the currently open ToxWindow. */
|
|
||||||
ToxWindow *get_active_window(void)
|
|
||||||
{
|
|
||||||
return active_window;
|
|
||||||
}
|
|
||||||
|
|
||||||
void force_refresh(WINDOW *w)
|
void force_refresh(WINDOW *w)
|
||||||
{
|
{
|
||||||
wclear(w);
|
wclear(w);
|
||||||
|
@ -121,10 +121,6 @@ struct ToxWindow {
|
|||||||
void(*onNickChange)(ToxWindow *, Tox *, uint32_t, const char *, size_t);
|
void(*onNickChange)(ToxWindow *, Tox *, uint32_t, const char *, size_t);
|
||||||
void(*onStatusChange)(ToxWindow *, Tox *, uint32_t, TOX_USER_STATUS);
|
void(*onStatusChange)(ToxWindow *, Tox *, uint32_t, TOX_USER_STATUS);
|
||||||
void(*onStatusMessageChange)(ToxWindow *, uint32_t, const char *, size_t);
|
void(*onStatusMessageChange)(ToxWindow *, uint32_t, const char *, size_t);
|
||||||
void(*onGroupMessage)(ToxWindow *, Tox *, uint32_t, uint32_t, TOX_MESSAGE_TYPE, const char *, size_t);
|
|
||||||
void(*onGroupInvite)(ToxWindow *, Tox *, int32_t, uint8_t, const char *, uint16_t);
|
|
||||||
void(*onGroupNamelistChange)(ToxWindow *, Tox *, uint32_t, uint32_t, TOX_CONFERENCE_STATE_CHANGE);
|
|
||||||
void(*onGroupTitleChange)(ToxWindow *, Tox *, uint32_t, uint32_t, const char *, size_t);
|
|
||||||
void(*onFileChunkRequest)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, size_t);
|
void(*onFileChunkRequest)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, size_t);
|
||||||
void(*onFileRecvChunk)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, const char *, size_t);
|
void(*onFileRecvChunk)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, const char *, size_t);
|
||||||
void(*onFileControl)(ToxWindow *, Tox *, uint32_t, uint32_t, TOX_FILE_CONTROL);
|
void(*onFileControl)(ToxWindow *, Tox *, uint32_t, uint32_t, TOX_FILE_CONTROL);
|
||||||
@ -132,6 +128,21 @@ struct ToxWindow {
|
|||||||
void(*onTypingChange)(ToxWindow *, Tox *, uint32_t, bool);
|
void(*onTypingChange)(ToxWindow *, Tox *, uint32_t, bool);
|
||||||
void(*onReadReceipt)(ToxWindow *, Tox *, uint32_t, uint32_t);
|
void(*onReadReceipt)(ToxWindow *, Tox *, uint32_t, uint32_t);
|
||||||
|
|
||||||
|
void(*onGroupInvite)(ToxWindow *, Tox *, uint32_t, const char *, size_t);
|
||||||
|
void(*onGroupMessage)(ToxWindow *, Tox *, uint32_t, uint32_t, TOX_MESSAGE_TYPE, const char *, size_t);
|
||||||
|
void(*onGroupPrivateMessage)(ToxWindow *, Tox *, uint32_t, uint32_t, const char *, size_t);
|
||||||
|
void(*onGroupPeerJoin)(ToxWindow *, Tox *, uint32_t, uint32_t);
|
||||||
|
void(*onGroupPeerExit)(ToxWindow *, Tox *, uint32_t, uint32_t, const char *, size_t);
|
||||||
|
void(*onGroupNickChange)(ToxWindow *, Tox *, uint32_t, uint32_t, const char *, size_t);
|
||||||
|
void(*onGroupStatusChange)(ToxWindow *, Tox *, uint32_t, uint32_t, TOX_USER_STATUS);
|
||||||
|
void(*onGroupTopicChange)(ToxWindow *, Tox *, uint32_t, uint32_t, const char *, size_t);
|
||||||
|
void(*onGroupPeerLimit)(ToxWindow *, Tox *, uint32_t, uint32_t);
|
||||||
|
void(*onGroupPrivacyState)(ToxWindow *, Tox *, uint32_t, TOX_GROUP_PRIVACY_STATE);
|
||||||
|
void(*onGroupPassword)(ToxWindow *, Tox *, uint32_t, const char *, size_t);
|
||||||
|
void(*onGroupSelfJoin)(ToxWindow *, Tox *, uint32_t);
|
||||||
|
void(*onGroupRejected)(ToxWindow *, Tox *, uint32_t, TOX_GROUP_JOIN_FAIL);
|
||||||
|
void(*onGroupModeration)(ToxWindow *, Tox *, uint32_t, uint32_t, uint32_t, TOX_GROUP_MOD_EVENT);
|
||||||
|
|
||||||
#ifdef AUDIO
|
#ifdef AUDIO
|
||||||
|
|
||||||
void(*onInvite)(ToxWindow *, ToxAV *, uint32_t, int);
|
void(*onInvite)(ToxWindow *, ToxAV *, uint32_t, int);
|
||||||
@ -259,7 +270,6 @@ void kill_all_windows(Tox *m); /* should only be called on shutdown */
|
|||||||
void on_window_resize(void);
|
void on_window_resize(void);
|
||||||
void force_refresh(WINDOW *w);
|
void force_refresh(WINDOW *w);
|
||||||
ToxWindow *get_window_ptr(int i);
|
ToxWindow *get_window_ptr(int i);
|
||||||
ToxWindow *get_active_window(void);
|
|
||||||
|
|
||||||
/* refresh inactive windows to prevent scrolling bugs.
|
/* refresh inactive windows to prevent scrolling bugs.
|
||||||
call at least once per second */
|
call at least once per second */
|
||||||
|
Reference in New Issue
Block a user