Compare commits
No commits in common. "master" and "v3.0.5" have entirely different histories.
16
.babelrc
@ -1,16 +0,0 @@
|
|||||||
{ "presets": [ [ "@babel/env"
|
|
||||||
, { "targets": { "browsers": [ "last 2 chrome versions"
|
|
||||||
, "last 2 chromeandroid versions"
|
|
||||||
, "firefox esr"
|
|
||||||
, "last 2 firefox versions"
|
|
||||||
, "last 2 edge versions"
|
|
||||||
, "safari >= 15"
|
|
||||||
, "ios >= 15"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
, "debug": true
|
|
||||||
, "include": [ ]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
3a88e73ee106ef675affb76a6399625bccf446e1
|
|
3
.gitattributes
vendored
@ -1,3 +0,0 @@
|
|||||||
*.php diff=php
|
|
||||||
*.css diff=css
|
|
||||||
*.scss diff=css
|
|
70
.gitignore
vendored
@ -1,13 +1,63 @@
|
|||||||
node_modules
|
# Linux
|
||||||
|
# backup files
|
||||||
|
*~
|
||||||
|
|
||||||
be.bastelstu.chat.tar.gz
|
# Windows
|
||||||
be.bastelstu.chat.tar
|
# thumbnails
|
||||||
files.tar
|
Thumbs.db
|
||||||
files_wcf.tar
|
|
||||||
acptemplates.tar
|
|
||||||
templates.tar
|
|
||||||
|
|
||||||
Bastelstu.be.Chat.js
|
# Mac OS X
|
||||||
Bastelstu.be.Chat.babel.js
|
# metadata
|
||||||
|
.DS_Store
|
||||||
|
# thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
files_wcf/js/Bastelstu.be.Chat.min.js
|
# Visual Studio PHP
|
||||||
|
*.sln
|
||||||
|
*.phpproj
|
||||||
|
*.puo
|
||||||
|
*.suo
|
||||||
|
*.cache
|
||||||
|
|
||||||
|
# Netbeans
|
||||||
|
nbproject/
|
||||||
|
catalog.xml
|
||||||
|
nbactions.xml
|
||||||
|
|
||||||
|
# Eclipse
|
||||||
|
.settings/
|
||||||
|
.buildpath
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
|
||||||
|
# SVN
|
||||||
|
# svn folders
|
||||||
|
.svn/
|
||||||
|
|
||||||
|
# PHPStorm
|
||||||
|
.idea/
|
||||||
|
.nameencodings
|
||||||
|
.xmlmisc
|
||||||
|
.xmlmodules
|
||||||
|
.xmlprojectCodeStyle
|
||||||
|
.xmlvcs.xml
|
||||||
|
*.imlworkspace
|
||||||
|
.xml
|
||||||
|
|
||||||
|
# Sublime Text 2
|
||||||
|
*.sublime-*
|
||||||
|
|
||||||
|
# Textmate
|
||||||
|
*.tmproj
|
||||||
|
|
||||||
|
# Community Framework
|
||||||
|
# Ignore packages build directly in the workspace. They can however be added manually via git add, if wanted.
|
||||||
|
*.tar
|
||||||
|
*.tar.gz
|
||||||
|
|
||||||
|
# Javascript - CoffeeScript is used instead ;)
|
||||||
|
*.js
|
||||||
|
.sass-cache
|
||||||
|
*.css
|
||||||
|
|
||||||
|
*.bak
|
||||||
|
@ -1 +0,0 @@
|
|||||||
require.build.js
|
|
@ -1,3 +0,0 @@
|
|||||||
semi: false
|
|
||||||
singleQuote: true
|
|
||||||
useTabs: true
|
|
16
.travis.yml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
language: php
|
||||||
|
php:
|
||||||
|
- 5.6
|
||||||
|
- 5.3
|
||||||
|
before_install:
|
||||||
|
- pyrus install pear/PHP_CodeSniffer
|
||||||
|
- phpenv rehash
|
||||||
|
before_script:
|
||||||
|
- git clone --branch=master --depth=1 --quiet git://github.com/WoltLab/WCF.git WCF
|
||||||
|
- rm WCF/CodeSniff/WCF/Sniffs/Namespaces/ClassMustBeImportedSniff.php
|
||||||
|
- rm WCF/CodeSniff/WCF/Sniffs/Namespaces/UseDeclarationSniff.php
|
||||||
|
- sed -i 's/<rule ref="WCF.Namespaces.ClassMustBeImported" \/>//' WCF/CodeSniff/WCF/ruleset.xml
|
||||||
|
- sed -i 's/<rule ref="WCF.Namespaces.UseDeclaration" \/>//' WCF/CodeSniff/WCF/ruleset.xml
|
||||||
|
script:
|
||||||
|
- find file -type f -name '*.php' |xargs -I file php -l file
|
||||||
|
- phpcs -p --extensions=php --standard="`pwd`/WCF/CodeSniff/WCF" file
|
8
.vscode/settings.json
vendored
@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"editor.rulers": [
|
|
||||||
{
|
|
||||||
"column": 120,
|
|
||||||
"color": "#ff00ff40"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
433
LICENSE
@ -1,104 +1,383 @@
|
|||||||
License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.
|
The following license applies to Tim’s Chat in whole:
|
||||||
“Business Source License” is a trademark of MariaDB Corporation Ab.
|
|
||||||
|
|
||||||
Parameters
|
The name "Tim’s Chat" may not be used in any derivated work, except for the
|
||||||
|
purpose of giving proper attribution to the original authors (e.g. “Based on
|
||||||
|
Tim’s Chat, developed in Tim’s Bastelstube”). Tim’s Chat in a whole is licensed
|
||||||
|
under the terms of
|
||||||
|
Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported
|
||||||
|
with exceptions made for some files, as specified below.
|
||||||
|
|
||||||
Licensor: Tim Düsterhus
|
-------------------------------------------------------------------------------
|
||||||
Licensed Work: Tim’s Chat 4.3
|
|
||||||
The Licensed Work is (c) 2010-2024 Tim Düsterhus
|
|
||||||
Additional Use Grant: You may use the Licensed Work when your application
|
|
||||||
uses the Licensed Work for a purpose that does neither
|
|
||||||
directly or indirectly generate revenue.
|
|
||||||
|
|
||||||
Change Date: 2028-06-15
|
The following license applies to all artwork, logos, images and any other
|
||||||
|
digital asset, unless specified otherwise in the file itself:
|
||||||
|
|
||||||
Change License: Version 2 or later of the GNU General Public License as
|
The files may ONLY be used in the context of and distributed together with an
|
||||||
published by the Free Software Foundation.
|
UNMODIFIED copy of Tim’s Chat. Any further RESTRICTION that applies to Tim’s Chat
|
||||||
|
in a whole (i.e. attribution, prohibition of commercial usage, etc.; see below)
|
||||||
|
applies to the artwork, logos, images and any other digital asset as well, any
|
||||||
|
further PERMISSION that applies to Tim’s Chat in a whole DOES NOT apply to the
|
||||||
|
artwork, logos, images and any other digital asset. Any use not explicitly
|
||||||
|
allowed by this license is PROHIBITED.
|
||||||
|
|
||||||
For information about alternative licensing arrangements for the Software,
|
If any provision of this License is invalid or unenforceable under
|
||||||
please email: tim <at the domain> bastelstu.be
|
applicable law, it shall not affect the validity or enforceability of
|
||||||
|
the remainder of the terms of this License, and without further action
|
||||||
|
by the parties to this agreement, such provision shall be reformed to
|
||||||
|
the minimum extent necessary to make such provision valid and
|
||||||
|
enforceable.
|
||||||
|
|
||||||
Notice
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
The Business Source License (this document, or the “License”) is not an Open
|
Creative Commons Legal Code
|
||||||
Source license. However, the Licensed Work will eventually be made available
|
|
||||||
under an Open Source License, as stated in this License.
|
|
||||||
|
|
||||||
For more information on the use of the Business Source License for MariaDB
|
Attribution-NonCommercial-ShareAlike 3.0 Unported
|
||||||
products, please visit the MariaDB Business Source License FAQ at
|
|
||||||
https://mariadb.com/bsl-faq-mariadb.
|
|
||||||
|
|
||||||
For more information on the use of the Business Source License generally,
|
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
|
||||||
please visit the Adopting and Developing Business Source License FAQ at
|
COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
|
||||||
https://mariadb.com/bsl-faq-adopting.
|
COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
|
||||||
|
AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
|
||||||
|
TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
|
||||||
|
BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
|
||||||
|
CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
|
||||||
|
CONDITIONS.
|
||||||
|
|
||||||
Business Source License 1.1
|
1. Definitions
|
||||||
|
|
||||||
Terms
|
a. "Adaptation" means a work based upon the Work, or upon the Work and
|
||||||
|
other pre-existing works, such as a translation, adaptation,
|
||||||
|
derivative work, arrangement of music or other alterations of a
|
||||||
|
literary or artistic work, or phonogram or performance and includes
|
||||||
|
cinematographic adaptations or any other form in which the Work may be
|
||||||
|
recast, transformed, or adapted including in any form recognizably
|
||||||
|
derived from the original, except that a work that constitutes a
|
||||||
|
Collection will not be considered an Adaptation for the purpose of
|
||||||
|
this License. For the avoidance of doubt, where the Work is a musical
|
||||||
|
work, performance or phonogram, the synchronization of the Work in
|
||||||
|
timed-relation with a moving image ("synching") will be considered an
|
||||||
|
Adaptation for the purpose of this License.
|
||||||
|
b. "Collection" means a collection of literary or artistic works, such as
|
||||||
|
encyclopedias and anthologies, or performances, phonograms or
|
||||||
|
broadcasts, or other works or subject matter other than works listed
|
||||||
|
in Section 1(g) below, which, by reason of the selection and
|
||||||
|
arrangement of their contents, constitute intellectual creations, in
|
||||||
|
which the Work is included in its entirety in unmodified form along
|
||||||
|
with one or more other contributions, each constituting separate and
|
||||||
|
independent works in themselves, which together are assembled into a
|
||||||
|
collective whole. A work that constitutes a Collection will not be
|
||||||
|
considered an Adaptation (as defined above) for the purposes of this
|
||||||
|
License.
|
||||||
|
c. "Distribute" means to make available to the public the original and
|
||||||
|
copies of the Work or Adaptation, as appropriate, through sale or
|
||||||
|
other transfer of ownership.
|
||||||
|
d. "License Elements" means the following high-level license attributes
|
||||||
|
as selected by Licensor and indicated in the title of this License:
|
||||||
|
Attribution, Noncommercial, ShareAlike.
|
||||||
|
e. "Licensor" means the individual, individuals, entity or entities that
|
||||||
|
offer(s) the Work under the terms of this License.
|
||||||
|
f. "Original Author" means, in the case of a literary or artistic work,
|
||||||
|
the individual, individuals, entity or entities who created the Work
|
||||||
|
or if no individual or entity can be identified, the publisher; and in
|
||||||
|
addition (i) in the case of a performance the actors, singers,
|
||||||
|
musicians, dancers, and other persons who act, sing, deliver, declaim,
|
||||||
|
play in, interpret or otherwise perform literary or artistic works or
|
||||||
|
expressions of folklore; (ii) in the case of a phonogram the producer
|
||||||
|
being the person or legal entity who first fixes the sounds of a
|
||||||
|
performance or other sounds; and, (iii) in the case of broadcasts, the
|
||||||
|
organization that transmits the broadcast.
|
||||||
|
g. "Work" means the literary and/or artistic work offered under the terms
|
||||||
|
of this License including without limitation any production in the
|
||||||
|
literary, scientific and artistic domain, whatever may be the mode or
|
||||||
|
form of its expression including digital form, such as a book,
|
||||||
|
pamphlet and other writing; a lecture, address, sermon or other work
|
||||||
|
of the same nature; a dramatic or dramatico-musical work; a
|
||||||
|
choreographic work or entertainment in dumb show; a musical
|
||||||
|
composition with or without words; a cinematographic work to which are
|
||||||
|
assimilated works expressed by a process analogous to cinematography;
|
||||||
|
a work of drawing, painting, architecture, sculpture, engraving or
|
||||||
|
lithography; a photographic work to which are assimilated works
|
||||||
|
expressed by a process analogous to photography; a work of applied
|
||||||
|
art; an illustration, map, plan, sketch or three-dimensional work
|
||||||
|
relative to geography, topography, architecture or science; a
|
||||||
|
performance; a broadcast; a phonogram; a compilation of data to the
|
||||||
|
extent it is protected as a copyrightable work; or a work performed by
|
||||||
|
a variety or circus performer to the extent it is not otherwise
|
||||||
|
considered a literary or artistic work.
|
||||||
|
h. "You" means an individual or entity exercising rights under this
|
||||||
|
License who has not previously violated the terms of this License with
|
||||||
|
respect to the Work, or who has received express permission from the
|
||||||
|
Licensor to exercise rights under this License despite a previous
|
||||||
|
violation.
|
||||||
|
i. "Publicly Perform" means to perform public recitations of the Work and
|
||||||
|
to communicate to the public those public recitations, by any means or
|
||||||
|
process, including by wire or wireless means or public digital
|
||||||
|
performances; to make available to the public Works in such a way that
|
||||||
|
members of the public may access these Works from a place and at a
|
||||||
|
place individually chosen by them; to perform the Work to the public
|
||||||
|
by any means or process and the communication to the public of the
|
||||||
|
performances of the Work, including by public digital performance; to
|
||||||
|
broadcast and rebroadcast the Work by any means including signs,
|
||||||
|
sounds or images.
|
||||||
|
j. "Reproduce" means to make copies of the Work by any means including
|
||||||
|
without limitation by sound or visual recordings and the right of
|
||||||
|
fixation and reproducing fixations of the Work, including storage of a
|
||||||
|
protected performance or phonogram in digital form or other electronic
|
||||||
|
medium.
|
||||||
|
|
||||||
The Licensor hereby grants you the right to copy, modify, create derivative
|
2. Fair Dealing Rights. Nothing in this License is intended to reduce,
|
||||||
works, redistribute, and make non-production use of the Licensed Work. The
|
limit, or restrict any uses free from copyright or rights arising from
|
||||||
Licensor may make an Additional Use Grant, above, permitting limited
|
limitations or exceptions that are provided for in connection with the
|
||||||
production use.
|
copyright protection under copyright law or other applicable laws.
|
||||||
|
|
||||||
Effective on the Change Date, or the fourth anniversary of the first publicly
|
3. License Grant. Subject to the terms and conditions of this License,
|
||||||
available distribution of a specific version of the Licensed Work under this
|
Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
|
||||||
License, whichever comes first, the Licensor hereby grants you rights under
|
perpetual (for the duration of the applicable copyright) license to
|
||||||
the terms of the Change License, and the rights granted in the paragraph
|
exercise the rights in the Work as stated below:
|
||||||
above terminate.
|
|
||||||
|
|
||||||
If your use of the Licensed Work does not comply with the requirements
|
a. to Reproduce the Work, to incorporate the Work into one or more
|
||||||
currently in effect as described in this License, you must purchase a
|
Collections, and to Reproduce the Work as incorporated in the
|
||||||
commercial license from the Licensor, its affiliated entities, or authorized
|
Collections;
|
||||||
resellers, or you must refrain from using the Licensed Work.
|
b. to create and Reproduce Adaptations provided that any such Adaptation,
|
||||||
|
including any translation in any medium, takes reasonable steps to
|
||||||
|
clearly label, demarcate or otherwise identify that changes were made
|
||||||
|
to the original Work. For example, a translation could be marked "The
|
||||||
|
original work was translated from English to Spanish," or a
|
||||||
|
modification could indicate "The original work has been modified.";
|
||||||
|
c. to Distribute and Publicly Perform the Work including as incorporated
|
||||||
|
in Collections; and,
|
||||||
|
d. to Distribute and Publicly Perform Adaptations.
|
||||||
|
|
||||||
All copies of the original and modified Licensed Work, and derivative works
|
The above rights may be exercised in all media and formats whether now
|
||||||
of the Licensed Work, are subject to this License. This License applies
|
known or hereafter devised. The above rights include the right to make
|
||||||
separately for each version of the Licensed Work and the Change Date may vary
|
such modifications as are technically necessary to exercise the rights in
|
||||||
for each version of the Licensed Work released by Licensor.
|
other media and formats. Subject to Section 8(f), all rights not expressly
|
||||||
|
granted by Licensor are hereby reserved, including but not limited to the
|
||||||
|
rights described in Section 4(e).
|
||||||
|
|
||||||
You must conspicuously display this License on each original or modified copy
|
4. Restrictions. The license granted in Section 3 above is expressly made
|
||||||
of the Licensed Work. If you receive the Licensed Work in original or
|
subject to and limited by the following restrictions:
|
||||||
modified form from a third party, the terms and conditions set forth in this
|
|
||||||
License apply to your use of that work.
|
|
||||||
|
|
||||||
Any use of the Licensed Work in violation of this License will automatically
|
a. You may Distribute or Publicly Perform the Work only under the terms
|
||||||
terminate your rights under this License for the current and all other
|
of this License. You must include a copy of, or the Uniform Resource
|
||||||
versions of the Licensed Work.
|
Identifier (URI) for, this License with every copy of the Work You
|
||||||
|
Distribute or Publicly Perform. You may not offer or impose any terms
|
||||||
|
on the Work that restrict the terms of this License or the ability of
|
||||||
|
the recipient of the Work to exercise the rights granted to that
|
||||||
|
recipient under the terms of the License. You may not sublicense the
|
||||||
|
Work. You must keep intact all notices that refer to this License and
|
||||||
|
to the disclaimer of warranties with every copy of the Work You
|
||||||
|
Distribute or Publicly Perform. When You Distribute or Publicly
|
||||||
|
Perform the Work, You may not impose any effective technological
|
||||||
|
measures on the Work that restrict the ability of a recipient of the
|
||||||
|
Work from You to exercise the rights granted to that recipient under
|
||||||
|
the terms of the License. This Section 4(a) applies to the Work as
|
||||||
|
incorporated in a Collection, but this does not require the Collection
|
||||||
|
apart from the Work itself to be made subject to the terms of this
|
||||||
|
License. If You create a Collection, upon notice from any Licensor You
|
||||||
|
must, to the extent practicable, remove from the Collection any credit
|
||||||
|
as required by Section 4(d), as requested. If You create an
|
||||||
|
Adaptation, upon notice from any Licensor You must, to the extent
|
||||||
|
practicable, remove from the Adaptation any credit as required by
|
||||||
|
Section 4(d), as requested.
|
||||||
|
b. You may Distribute or Publicly Perform an Adaptation only under: (i)
|
||||||
|
the terms of this License; (ii) a later version of this License with
|
||||||
|
the same License Elements as this License; (iii) a Creative Commons
|
||||||
|
jurisdiction license (either this or a later license version) that
|
||||||
|
contains the same License Elements as this License (e.g.,
|
||||||
|
Attribution-NonCommercial-ShareAlike 3.0 US) ("Applicable License").
|
||||||
|
You must include a copy of, or the URI, for Applicable License with
|
||||||
|
every copy of each Adaptation You Distribute or Publicly Perform. You
|
||||||
|
may not offer or impose any terms on the Adaptation that restrict the
|
||||||
|
terms of the Applicable License or the ability of the recipient of the
|
||||||
|
Adaptation to exercise the rights granted to that recipient under the
|
||||||
|
terms of the Applicable License. You must keep intact all notices that
|
||||||
|
refer to the Applicable License and to the disclaimer of warranties
|
||||||
|
with every copy of the Work as included in the Adaptation You
|
||||||
|
Distribute or Publicly Perform. When You Distribute or Publicly
|
||||||
|
Perform the Adaptation, You may not impose any effective technological
|
||||||
|
measures on the Adaptation that restrict the ability of a recipient of
|
||||||
|
the Adaptation from You to exercise the rights granted to that
|
||||||
|
recipient under the terms of the Applicable License. This Section 4(b)
|
||||||
|
applies to the Adaptation as incorporated in a Collection, but this
|
||||||
|
does not require the Collection apart from the Adaptation itself to be
|
||||||
|
made subject to the terms of the Applicable License.
|
||||||
|
c. You may not exercise any of the rights granted to You in Section 3
|
||||||
|
above in any manner that is primarily intended for or directed toward
|
||||||
|
commercial advantage or private monetary compensation. The exchange of
|
||||||
|
the Work for other copyrighted works by means of digital file-sharing
|
||||||
|
or otherwise shall not be considered to be intended for or directed
|
||||||
|
toward commercial advantage or private monetary compensation, provided
|
||||||
|
there is no payment of any monetary compensation in con-nection with
|
||||||
|
the exchange of copyrighted works.
|
||||||
|
d. If You Distribute, or Publicly Perform the Work or any Adaptations or
|
||||||
|
Collections, You must, unless a request has been made pursuant to
|
||||||
|
Section 4(a), keep intact all copyright notices for the Work and
|
||||||
|
provide, reasonable to the medium or means You are utilizing: (i) the
|
||||||
|
name of the Original Author (or pseudonym, if applicable) if supplied,
|
||||||
|
and/or if the Original Author and/or Licensor designate another party
|
||||||
|
or parties (e.g., a sponsor institute, publishing entity, journal) for
|
||||||
|
attribution ("Attribution Parties") in Licensor's copyright notice,
|
||||||
|
terms of service or by other reasonable means, the name of such party
|
||||||
|
or parties; (ii) the title of the Work if supplied; (iii) to the
|
||||||
|
extent reasonably practicable, the URI, if any, that Licensor
|
||||||
|
specifies to be associated with the Work, unless such URI does not
|
||||||
|
refer to the copyright notice or licensing information for the Work;
|
||||||
|
and, (iv) consistent with Section 3(b), in the case of an Adaptation,
|
||||||
|
a credit identifying the use of the Work in the Adaptation (e.g.,
|
||||||
|
"French translation of the Work by Original Author," or "Screenplay
|
||||||
|
based on original Work by Original Author"). The credit required by
|
||||||
|
this Section 4(d) may be implemented in any reasonable manner;
|
||||||
|
provided, however, that in the case of a Adaptation or Collection, at
|
||||||
|
a minimum such credit will appear, if a credit for all contributing
|
||||||
|
authors of the Adaptation or Collection appears, then as part of these
|
||||||
|
credits and in a manner at least as prominent as the credits for the
|
||||||
|
other contributing authors. For the avoidance of doubt, You may only
|
||||||
|
use the credit required by this Section for the purpose of attribution
|
||||||
|
in the manner set out above and, by exercising Your rights under this
|
||||||
|
License, You may not implicitly or explicitly assert or imply any
|
||||||
|
connection with, sponsorship or endorsement by the Original Author,
|
||||||
|
Licensor and/or Attribution Parties, as appropriate, of You or Your
|
||||||
|
use of the Work, without the separate, express prior written
|
||||||
|
permission of the Original Author, Licensor and/or Attribution
|
||||||
|
Parties.
|
||||||
|
e. For the avoidance of doubt:
|
||||||
|
|
||||||
This License does not grant you any right in any trademark or logo of
|
i. Non-waivable Compulsory License Schemes. In those jurisdictions in
|
||||||
Licensor or its affiliates (provided that you may use a trademark or logo of
|
which the right to collect royalties through any statutory or
|
||||||
Licensor as expressly required by this License).
|
compulsory licensing scheme cannot be waived, the Licensor
|
||||||
|
reserves the exclusive right to collect such royalties for any
|
||||||
|
exercise by You of the rights granted under this License;
|
||||||
|
ii. Waivable Compulsory License Schemes. In those jurisdictions in
|
||||||
|
which the right to collect royalties through any statutory or
|
||||||
|
compulsory licensing scheme can be waived, the Licensor reserves
|
||||||
|
the exclusive right to collect such royalties for any exercise by
|
||||||
|
You of the rights granted under this License if Your exercise of
|
||||||
|
such rights is for a purpose or use which is otherwise than
|
||||||
|
noncommercial as permitted under Section 4(c) and otherwise waives
|
||||||
|
the right to collect royalties through any statutory or compulsory
|
||||||
|
licensing scheme; and,
|
||||||
|
iii. Voluntary License Schemes. The Licensor reserves the right to
|
||||||
|
collect royalties, whether individually or, in the event that the
|
||||||
|
Licensor is a member of a collecting society that administers
|
||||||
|
voluntary licensing schemes, via that society, from any exercise
|
||||||
|
by You of the rights granted under this License that is for a
|
||||||
|
purpose or use which is otherwise than noncommercial as permitted
|
||||||
|
under Section 4(c).
|
||||||
|
f. Except as otherwise agreed in writing by the Licensor or as may be
|
||||||
|
otherwise permitted by applicable law, if You Reproduce, Distribute or
|
||||||
|
Publicly Perform the Work either by itself or as part of any
|
||||||
|
Adaptations or Collections, You must not distort, mutilate, modify or
|
||||||
|
take other derogatory action in relation to the Work which would be
|
||||||
|
prejudicial to the Original Author's honor or reputation. Licensor
|
||||||
|
agrees that in those jurisdictions (e.g. Japan), in which any exercise
|
||||||
|
of the right granted in Section 3(b) of this License (the right to
|
||||||
|
make Adaptations) would be deemed to be a distortion, mutilation,
|
||||||
|
modification or other derogatory action prejudicial to the Original
|
||||||
|
Author's honor and reputation, the Licensor will waive or not assert,
|
||||||
|
as appropriate, this Section, to the fullest extent permitted by the
|
||||||
|
applicable national law, to enable You to reasonably exercise Your
|
||||||
|
right under Section 3(b) of this License (right to make Adaptations)
|
||||||
|
but not otherwise.
|
||||||
|
|
||||||
TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
|
5. Representations, Warranties and Disclaimer
|
||||||
AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
|
|
||||||
TITLE.
|
|
||||||
|
|
||||||
MariaDB hereby grants you permission to use this License’s text to license
|
UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING AND TO THE
|
||||||
your works, and to refer to it using the trademark “Business Source License”,
|
FULLEST EXTENT PERMITTED BY APPLICABLE LAW, LICENSOR OFFERS THE WORK AS-IS
|
||||||
as long as you comply with the Covenants of Licensor below.
|
AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE
|
||||||
|
WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT
|
||||||
|
LIMITATION, WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS,
|
||||||
|
ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT
|
||||||
|
DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED
|
||||||
|
WARRANTIES, SO THIS EXCLUSION MAY NOT APPLY TO YOU.
|
||||||
|
|
||||||
Covenants of Licensor
|
6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
|
||||||
|
LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR
|
||||||
|
ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES
|
||||||
|
ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
In consideration of the right to use this License’s text and the “Business
|
7. Termination
|
||||||
Source License” name and trademark, Licensor covenants to MariaDB, and to all
|
|
||||||
other recipients of the licensed work to be provided by Licensor:
|
|
||||||
|
|
||||||
1. To specify as the Change License the GPL Version 2.0 or any later version,
|
a. This License and the rights granted hereunder will terminate
|
||||||
or a license that is compatible with GPL Version 2.0 or a later version,
|
automatically upon any breach by You of the terms of this License.
|
||||||
where “compatible” means that software provided under the Change License can
|
Individuals or entities who have received Adaptations or Collections
|
||||||
be included in a program with software provided under GPL Version 2.0 or a
|
from You under this License, however, will not have their licenses
|
||||||
later version. Licensor may specify additional Change Licenses without
|
terminated provided such individuals or entities remain in full
|
||||||
limitation.
|
compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
|
||||||
|
survive any termination of this License.
|
||||||
|
b. Subject to the above terms and conditions, the license granted here is
|
||||||
|
perpetual (for the duration of the applicable copyright in the Work).
|
||||||
|
Notwithstanding the above, Licensor reserves the right to release the
|
||||||
|
Work under different license terms or to stop distributing the Work at
|
||||||
|
any time; provided, however that any such election will not serve to
|
||||||
|
withdraw this License (or any other license that has been, or is
|
||||||
|
required to be, granted under the terms of this License), and this
|
||||||
|
License will continue in full force and effect unless terminated as
|
||||||
|
stated above.
|
||||||
|
|
||||||
2. To either: (a) specify an additional grant of rights to use that does not
|
8. Miscellaneous
|
||||||
impose any additional restriction on the right granted in this License, as
|
|
||||||
the Additional Use Grant; or (b) insert the text “None”.
|
|
||||||
|
|
||||||
3. To specify a Change Date.
|
a. Each time You Distribute or Publicly Perform the Work or a Collection,
|
||||||
|
the Licensor offers to the recipient a license to the Work on the same
|
||||||
|
terms and conditions as the license granted to You under this License.
|
||||||
|
b. Each time You Distribute or Publicly Perform an Adaptation, Licensor
|
||||||
|
offers to the recipient a license to the original Work on the same
|
||||||
|
terms and conditions as the license granted to You under this License.
|
||||||
|
c. If any provision of this License is invalid or unenforceable under
|
||||||
|
applicable law, it shall not affect the validity or enforceability of
|
||||||
|
the remainder of the terms of this License, and without further action
|
||||||
|
by the parties to this agreement, such provision shall be reformed to
|
||||||
|
the minimum extent necessary to make such provision valid and
|
||||||
|
enforceable.
|
||||||
|
d. No term or provision of this License shall be deemed waived and no
|
||||||
|
breach consented to unless such waiver or consent shall be in writing
|
||||||
|
and signed by the party to be charged with such waiver or consent.
|
||||||
|
e. This License constitutes the entire agreement between the parties with
|
||||||
|
respect to the Work licensed here. There are no understandings,
|
||||||
|
agreements or representations with respect to the Work not specified
|
||||||
|
here. Licensor shall not be bound by any additional provisions that
|
||||||
|
may appear in any communication from You. This License may not be
|
||||||
|
modified without the mutual written agreement of the Licensor and You.
|
||||||
|
f. The rights granted under, and the subject matter referenced, in this
|
||||||
|
License were drafted utilizing the terminology of the Berne Convention
|
||||||
|
for the Protection of Literary and Artistic Works (as amended on
|
||||||
|
September 28, 1979), the Rome Convention of 1961, the WIPO Copyright
|
||||||
|
Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996
|
||||||
|
and the Universal Copyright Convention (as revised on July 24, 1971).
|
||||||
|
These rights and subject matter take effect in the relevant
|
||||||
|
jurisdiction in which the License terms are sought to be enforced
|
||||||
|
according to the corresponding provisions of the implementation of
|
||||||
|
those treaty provisions in the applicable national law. If the
|
||||||
|
standard suite of rights granted under applicable copyright law
|
||||||
|
includes additional rights not granted under this License, such
|
||||||
|
additional rights are deemed to be included in the License; this
|
||||||
|
License is not intended to restrict the license of any rights under
|
||||||
|
applicable law.
|
||||||
|
|
||||||
|
|
||||||
|
Creative Commons Notice
|
||||||
|
|
||||||
|
Creative Commons is not a party to this License, and makes no warranty
|
||||||
|
whatsoever in connection with the Work. Creative Commons will not be
|
||||||
|
liable to You or any party on any legal theory for any damages
|
||||||
|
whatsoever, including without limitation any general, special,
|
||||||
|
incidental or consequential damages arising in connection to this
|
||||||
|
license. Notwithstanding the foregoing two (2) sentences, if Creative
|
||||||
|
Commons has expressly identified itself as the Licensor hereunder, it
|
||||||
|
shall have all rights and obligations of Licensor.
|
||||||
|
|
||||||
|
Except for the limited purpose of indicating to the public that the
|
||||||
|
Work is licensed under the CCPL, Creative Commons does not authorize
|
||||||
|
the use by either party of the trademark "Creative Commons" or any
|
||||||
|
related trademark or logo of Creative Commons without the prior
|
||||||
|
written consent of Creative Commons. Any permitted use will be in
|
||||||
|
compliance with Creative Commons' then-current trademark usage
|
||||||
|
guidelines, as may be published on its website or otherwise made
|
||||||
|
available upon request from time to time. For the avoidance of doubt,
|
||||||
|
this trademark restriction does not form part of this License.
|
||||||
|
|
||||||
|
Creative Commons may be contacted at http://creativecommons.org/.
|
||||||
|
|
||||||
4. Not to modify this License in any other way.
|
|
||||||
|
46
Makefile
@ -1,46 +0,0 @@
|
|||||||
FILES = $(shell find files -type f)
|
|
||||||
WCF_FILES = $(shell find files_wcf -type f)
|
|
||||||
JS_MODULE_FILES = $(shell find files_wcf/js/Bastelstu.be -type f)
|
|
||||||
|
|
||||||
all: be.bastelstu.chat.tar be.bastelstu.chat.tar.gz
|
|
||||||
|
|
||||||
be.bastelstu.chat.tar.gz: be.bastelstu.chat.tar
|
|
||||||
gzip -9 < $< > $@
|
|
||||||
|
|
||||||
be.bastelstu.chat.tar: files.tar files_wcf.tar acptemplates.tar templates.tar *.xml LICENSE sql/*.sql language/*.xml
|
|
||||||
tar cvf $@ --mtime="@$(shell git log -1 --format=%ct)" --owner=0 --group=0 --numeric-owner --exclude-vcs -- $^
|
|
||||||
|
|
||||||
files.tar: $(FILES)
|
|
||||||
files_wcf.tar: $(WCF_FILES) files_wcf/js/Bastelstu.be.Chat.min.js
|
|
||||||
acptemplates.tar: acptemplates/*.tpl
|
|
||||||
templates.tar: templates/*.tpl
|
|
||||||
|
|
||||||
%.tar:
|
|
||||||
tar cvf $@ --mtime="@$(shell git log -1 --format=%ct)" --owner=0 --group=0 --numeric-owner --exclude-vcs -C $* -- $(^:$*/%=%)
|
|
||||||
|
|
||||||
files_wcf/js/Bastelstu.be.Chat.min.js: Bastelstu.be.Chat.babel.js
|
|
||||||
yarn run terser --comments '/Copyright|stackoverflow/' -m -c pure_funcs=[console.debug] --verbose --timings -o $@ $^
|
|
||||||
|
|
||||||
Bastelstu.be.Chat.babel.js: Bastelstu.be.Chat.js .babelrc
|
|
||||||
yarn run babel $< --out-file $@
|
|
||||||
|
|
||||||
Bastelstu.be.Chat.js: $(JS_MODULE_FILES)
|
|
||||||
yarn run r_js -o require.build.js
|
|
||||||
|
|
||||||
clean:
|
|
||||||
-rm -f files.tar
|
|
||||||
-rm -f files_wcf.tar
|
|
||||||
-rm -f templates.tar
|
|
||||||
-rm -f acptemplates.tar
|
|
||||||
-rm -f Bastelstu.be.Chat.js
|
|
||||||
-rm -f Bastelstu.be.Chat.babel.js
|
|
||||||
-rm -f files_wcf/js/Bastelstu.be.Chat.min.js
|
|
||||||
|
|
||||||
distclean: clean
|
|
||||||
-rm -f be.bastelstu.chat.tar
|
|
||||||
-rm -f be.bastelstu.chat.tar.gz
|
|
||||||
|
|
||||||
constants.php: option.xml
|
|
||||||
(echo "<?php" ; xq -r '.data.import.options.option[] | "define(\"" + (.["@name"] | ascii_upcase) + "\", " + .defaultvalue + ");"' < option.xml) > constants.php
|
|
||||||
|
|
||||||
.PHONY: distclean clean
|
|
10
README.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
Tim’s Chat 3.0
|
||||||
|
==============
|
||||||
|
|
||||||
|
Tim’s Chat is a chat-plugin for WoltLab Community Framework.
|
||||||
|
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
For licensing information refer to the LICENSE file in this folder.
|
@ -11,11 +11,7 @@
|
|||||||
</categories>
|
</categories>
|
||||||
|
|
||||||
<options>
|
<options>
|
||||||
<option name="user.canSee">
|
<option name="user.canEnter">
|
||||||
<objecttype>be.bastelstu.chat.room</objecttype>
|
|
||||||
<categoryname>user</categoryname>
|
|
||||||
</option>
|
|
||||||
<option name="user.canSeeLog">
|
|
||||||
<objecttype>be.bastelstu.chat.room</objecttype>
|
<objecttype>be.bastelstu.chat.room</objecttype>
|
||||||
<categoryname>user</categoryname>
|
<categoryname>user</categoryname>
|
||||||
</option>
|
</option>
|
||||||
@ -23,7 +19,13 @@
|
|||||||
<objecttype>be.bastelstu.chat.room</objecttype>
|
<objecttype>be.bastelstu.chat.room</objecttype>
|
||||||
<categoryname>user</categoryname>
|
<categoryname>user</categoryname>
|
||||||
</option>
|
</option>
|
||||||
<option name="mod.canIgnoreUserLimit">
|
|
||||||
|
|
||||||
|
<option name="mod.canAlwaysEnter">
|
||||||
|
<objecttype>be.bastelstu.chat.room</objecttype>
|
||||||
|
<categoryname>mod</categoryname>
|
||||||
|
</option>
|
||||||
|
<option name="mod.canAlwaysWrite">
|
||||||
<objecttype>be.bastelstu.chat.room</objecttype>
|
<objecttype>be.bastelstu.chat.room</objecttype>
|
||||||
<categoryname>mod</categoryname>
|
<categoryname>mod</categoryname>
|
||||||
</option>
|
</option>
|
||||||
@ -31,18 +33,10 @@
|
|||||||
<objecttype>be.bastelstu.chat.room</objecttype>
|
<objecttype>be.bastelstu.chat.room</objecttype>
|
||||||
<categoryname>mod</categoryname>
|
<categoryname>mod</categoryname>
|
||||||
</option>
|
</option>
|
||||||
<option name="mod.canIgnoreMute">
|
|
||||||
<objecttype>be.bastelstu.chat.room</objecttype>
|
|
||||||
<categoryname>mod</categoryname>
|
|
||||||
</option>
|
|
||||||
<option name="mod.canBan">
|
<option name="mod.canBan">
|
||||||
<objecttype>be.bastelstu.chat.room</objecttype>
|
<objecttype>be.bastelstu.chat.room</objecttype>
|
||||||
<categoryname>mod</categoryname>
|
<categoryname>mod</categoryname>
|
||||||
</option>
|
</option>
|
||||||
<option name="mod.canIgnoreBan">
|
|
||||||
<objecttype>be.bastelstu.chat.room</objecttype>
|
|
||||||
<categoryname>mod</categoryname>
|
|
||||||
</option>
|
|
||||||
</options>
|
</options>
|
||||||
</import>
|
</import>
|
||||||
</data>
|
</data>
|
40
acpMenu.xml
@ -2,41 +2,39 @@
|
|||||||
<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/maelstrom/acpMenu.xsd">
|
<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/maelstrom/acpMenu.xsd">
|
||||||
<import>
|
<import>
|
||||||
<acpmenuitem name="chat.acp.menu.link.chat">
|
<acpmenuitem name="chat.acp.menu.link.chat">
|
||||||
<parent>wcf.acp.menu.link.application</parent>
|
<parent>wcf.acp.menu.link.community</parent>
|
||||||
</acpmenuitem>
|
</acpmenuitem>
|
||||||
|
|
||||||
<acpmenuitem name="chat.acp.menu.link.room.list">
|
<acpmenuitem name="chat.acp.menu.link.room.list">
|
||||||
<controller>chat\acp\page\RoomListPage</controller>
|
<controller><![CDATA[chat\acp\page\RoomListPage]]></controller>
|
||||||
<parent>chat.acp.menu.link.chat</parent>
|
<parent>chat.acp.menu.link.chat</parent>
|
||||||
<permissions>admin.chat.canManageRoom</permissions>
|
<permissions>admin.chat.canEditRoom,admin.chat.canDeleteRoom</permissions>
|
||||||
<showorder>1</showorder>
|
<showorder>1</showorder>
|
||||||
</acpmenuitem>
|
</acpmenuitem>
|
||||||
|
|
||||||
<acpmenuitem name="chat.acp.menu.link.room.add">
|
<acpmenuitem name="chat.acp.menu.link.room.add">
|
||||||
<controller>chat\acp\form\RoomAddForm</controller>
|
<controller><![CDATA[chat\acp\form\RoomAddForm]]></controller>
|
||||||
<parent>chat.acp.menu.link.room.list</parent>
|
|
||||||
<permissions>admin.chat.canManageRoom</permissions>
|
|
||||||
<icon>plus</icon>
|
|
||||||
</acpmenuitem>
|
|
||||||
|
|
||||||
<acpmenuitem name="chat.acp.menu.link.command.trigger.list">
|
|
||||||
<controller>chat\acp\page\CommandTriggerListPage</controller>
|
|
||||||
<parent>chat.acp.menu.link.chat</parent>
|
<parent>chat.acp.menu.link.chat</parent>
|
||||||
<permissions>admin.chat.canManageTriggers</permissions>
|
<permissions>admin.chat.canAddRoom</permissions>
|
||||||
</acpmenuitem>
|
<showorder>2</showorder>
|
||||||
|
|
||||||
<acpmenuitem name="chat.acp.menu.link.command.trigger.add">
|
|
||||||
<controller>chat\acp\form\CommandTriggerAddForm</controller>
|
|
||||||
<parent>chat.acp.menu.link.command.trigger.list</parent>
|
|
||||||
<permissions>admin.chat.canManageTriggers</permissions>
|
|
||||||
<icon>plus</icon>
|
|
||||||
</acpmenuitem>
|
</acpmenuitem>
|
||||||
|
|
||||||
<acpmenuitem name="chat.acp.menu.link.suspension.list">
|
<acpmenuitem name="chat.acp.menu.link.suspension.list">
|
||||||
<controller>chat\acp\page\SuspensionListPage</controller>
|
<controller><![CDATA[chat\acp\page\ChatSuspensionListPage]]></controller>
|
||||||
<parent>chat.acp.menu.link.chat</parent>
|
<parent>chat.acp.menu.link.chat</parent>
|
||||||
<permissions>admin.chat.canManageSuspensions</permissions>
|
<permissions>admin.chat.canManageSuspensions</permissions>
|
||||||
|
<showorder>3</showorder>
|
||||||
|
</acpmenuitem>
|
||||||
|
|
||||||
|
<acpmenuitem name="chat.acp.menu.link.log">
|
||||||
|
<controller><![CDATA[chat\acp\page\MessageLogPage]]></controller>
|
||||||
|
<parent>chat.acp.menu.link.chat</parent>
|
||||||
|
<permissions>admin.chat.canReadLog</permissions>
|
||||||
|
<showorder>4</showorder>
|
||||||
</acpmenuitem>
|
</acpmenuitem>
|
||||||
</import>
|
</import>
|
||||||
</data>
|
|
||||||
|
|
||||||
|
<delete>
|
||||||
|
<acpmenuitem name="chat.acp.menu.link" />
|
||||||
|
</delete>
|
||||||
|
</data>
|
||||||
|
1
acptemplate/__headerLogo.tpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
{if $__chat->isActiveApplication()}<img src="{$__wcf->getPath('chat')}images/chatLogo.png" style="width: 246px; height: 90px;" alt="" />{/if}
|
26
acptemplate/__messageLogTable.tpl
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{if $messages|count > 0}
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{lang}wcf.global.objectID{/lang}</th>
|
||||||
|
<th>{lang}chat.global.time{/lang}</th>
|
||||||
|
<th colspan="2">{lang}wcf.user.username{/lang}</th>
|
||||||
|
<th>{lang}chat.acp.log.message{/lang}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{foreach from=$messages item="message"}
|
||||||
|
<tr>
|
||||||
|
<td class="columnID">{$message->messageID}</td>
|
||||||
|
<td style="width: 1px !important;">{$message->time|date:"H:i:s"}</td>
|
||||||
|
<td class="columnIcon"><p class="framed">{@$message->getUserProfile()->getAvatar()->getImageTag(24)}</p></td>
|
||||||
|
<td class="columnTitle columnUsername right" style="width: 1px !important;">{$message->username}</td>
|
||||||
|
<td>{@$message->getFormattedMessage("text/simplified-html")}</td>
|
||||||
|
</tr>
|
||||||
|
{/foreach}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{else}
|
||||||
|
<p class="info">{lang}wcf.global.noItems{/lang}</p>
|
||||||
|
{/if}
|
4
acptemplate/__softwareVersions.tpl
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<dl>
|
||||||
|
<dt>{lang}wcf.acp.index.system.software.chatVersion{/lang}</dt>
|
||||||
|
<dd>{$__chat->getPackage()->packageVersion}</dd>
|
||||||
|
</dl>
|
166
acptemplate/chatSuspensionList.tpl
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
{include file='header' pageTitle='chat.acp.suspension.list'}
|
||||||
|
|
||||||
|
<script data-relocate="true">
|
||||||
|
//<![CDATA[
|
||||||
|
$(function() {
|
||||||
|
new WCF.Search.User('#username', null, false, [ ], false);
|
||||||
|
new WCF.Search.User('#issuerUsername', null, false, [ ], false);
|
||||||
|
|
||||||
|
var proxy = new WCF.Action.Proxy({
|
||||||
|
success: function (data, textStatus, jqXHR) {
|
||||||
|
$('.jsSuspensionRow').each(function(index, row) {
|
||||||
|
var row = $(row);
|
||||||
|
if (WCF.inArray(row.data('objectID'), data.objectIDs)) {
|
||||||
|
row.find('.jsRevokeButton').addClass('disabled').removeClass('pointer').off('click');
|
||||||
|
|
||||||
|
(new WCF.System.Notification('{"chat.acp.suspension.revoke.success"|language|encodeJS}')).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$('.jsRevokeButton:not(.disabled)').click(function () {
|
||||||
|
var objectID = $(this).parents('.jsSuspensionRow').data('objectID');
|
||||||
|
|
||||||
|
WCF.System.Confirmation.show($(this).data('confirmMessage'), $.proxy(function (action) {
|
||||||
|
if (action === 'confirm') {
|
||||||
|
proxy.setOption('data', {
|
||||||
|
actionName: 'revoke',
|
||||||
|
className: '\\chat\\data\\suspension\\SuspensionAction',
|
||||||
|
objectIDs: [ objectID ]
|
||||||
|
});
|
||||||
|
proxy.sendRequest();
|
||||||
|
}
|
||||||
|
}, this));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
//]]>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<header class="boxHeadline">
|
||||||
|
<h1>{lang}chat.acp.suspension.list{/lang}</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<form method="post" action="{link controller='ChatSuspensionList' application='chat'}{/link}">
|
||||||
|
<div class="container containerPadding marginTop">
|
||||||
|
<fieldset>
|
||||||
|
<legend>{lang}wcf.global.filter{/lang}</legend>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dd>
|
||||||
|
<label><input type="checkbox" id="displayRevoked" name="displayRevoked" value="1"{if $displayRevoked} checked="checked"{/if} /> {lang}chat.acp.suspension.displayRevoked{/lang}</label>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt><label for="username">{lang}wcf.user.username{/lang}</label></dt>
|
||||||
|
<dd>
|
||||||
|
<input type="text" id="username" name="username" class="medium" value="{$username}" />
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt><label for="issuerUsername">{lang}chat.acp.suspension.issuer{/lang}</label></dt>
|
||||||
|
<dd>
|
||||||
|
<input type="text" id="issuerUsername" name="issuerUsername" class="medium" value="{$issuerUsername}" />
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt><label for="roomID">{lang}chat.global.room{/lang}</label></dt>
|
||||||
|
<dd>
|
||||||
|
<select id="roomID" name="roomID">
|
||||||
|
<option value="-1"{if $roomID == -1} selected="selected"{/if}></option>
|
||||||
|
<option value="0"{if $roomID == 0} selected="selected"{/if}>{lang}chat.room.global{/lang}</option>
|
||||||
|
<option value="" disabled="disabled">-------------</option>
|
||||||
|
{foreach from=$availableRooms key=id item=room}
|
||||||
|
<option value="{$id}" {if $roomID == $id}selected="selected"{/if}>{$room}</option>
|
||||||
|
{/foreach}
|
||||||
|
</select>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt><label for="suspensionType">{lang}chat.acp.suspension.type{/lang}</label></dt>
|
||||||
|
<dd>
|
||||||
|
<select id="suspensionType" name="suspensionType">
|
||||||
|
<option value=""{if $suspensionType === null} selected="selected"{/if}></option>
|
||||||
|
<option value="{'\chat\data\suspension\Suspension::TYPE_MUTE'|constant}"{if $suspensionType == '\chat\data\suspension\Suspension::TYPE_MUTE'|constant} selected="selected"{/if}>{lang}chat.suspension.{'\chat\data\suspension\Suspension::TYPE_MUTE'|constant}{/lang}</option>
|
||||||
|
<option value="{'\chat\data\suspension\Suspension::TYPE_BAN'|constant}"{if $suspensionType == '\chat\data\suspension\Suspension::TYPE_BAN'|constant} selected="selected"{/if}>{lang}chat.suspension.{'\chat\data\suspension\Suspension::TYPE_BAN'|constant}{/lang}</option>
|
||||||
|
</select>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="formSubmit">
|
||||||
|
<input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{if $objects|count}
|
||||||
|
{capture assign=additionalParameters}{*
|
||||||
|
*}{if $userID}&userID={$userID}{/if}{*
|
||||||
|
*}{if $issuerUserID}&issuerUserID={$issuerUserID}{/if}{*
|
||||||
|
*}{if $roomID}&roomID={$roomID}{/if}{*
|
||||||
|
*}{if $suspensionType}&suspensionType={$suspensionType}{/if}{*
|
||||||
|
*}{if $displayRevoked}&displayRevoked={$displayRevoked}{/if}{*
|
||||||
|
*}{/capture}
|
||||||
|
|
||||||
|
<div class="contentNavigation">
|
||||||
|
{pages print=true assign=pagesLinks application="chat" controller="ChatSuspensionList" link="pageNo=%d$additionalParameters"}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tabularBox tabularBoxTitle marginTop">
|
||||||
|
<header>
|
||||||
|
<h2>{lang}chat.acp.suspension.list{/lang} <span class="badge badgeInverse">{#$items}</span></h2>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="columnID{if $sortField == 'suspensionID'} active {@$sortOrder}{/if}" colspan="2"><a href="{link application='chat' controller='ChatSuspensionList'}pageNo={@$pageNo}&sortField=suspensionID&sortOrder={if $sortField == 'suspensionID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$additionalParameters}{/link}">{lang}wcf.global.objectID{/lang}</a></th>
|
||||||
|
<th class="columnUsername{if $sortField == 'username'} active {@$sortOrder}{/if}"><a href="{link application='chat' controller='ChatSuspensionList'}pageNo={@$pageNo}&sortField=username&sortOrder={if $sortField == 'username' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$additionalParameters}{/link}">{lang}wcf.user.username{/lang}</a></th>
|
||||||
|
<th class="columnRoomID{if $sortField == 'roomID'} active {@$sortOrder}{/if}"><a href="{link application='chat' controller='ChatSuspensionList'}pageNo={@$pageNo}&sortField=roomID&sortOrder={if $sortField == 'roomID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$additionalParameters}{/link}">{lang}chat.global.room{/lang}</a></th>
|
||||||
|
<th class="columnSuspensionType{if $sortField == 'type'} active {@$sortOrder}{/if}"><a href="{link application='chat' controller='ChatSuspensionList'}pageNo={@$pageNo}&sortField=type&sortOrder={if $sortField == 'type' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$additionalParameters}{/link}">{lang}chat.acp.suspension.type{/lang}</a></th>
|
||||||
|
<th class="columnTime{if $sortField == 'time'} active {@$sortOrder}{/if}"><a href="{link application='chat' controller='ChatSuspensionList'}pageNo={@$pageNo}&sortField=time&sortOrder={if $sortField == 'time' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$additionalParameters}{/link}">{lang}chat.global.time{/lang}</a></th>
|
||||||
|
<th class="columnExpires{if $sortField == 'expires'} active {@$sortOrder}{/if}"><a href="{link application='chat' controller='ChatSuspensionList'}pageNo={@$pageNo}&sortField=expires&sortOrder={if $sortField == 'expires' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$additionalParameters}{/link}">{lang}chat.global.expires{/lang}</a></th>
|
||||||
|
<th class="columnIssuer{if $sortField == 'issuer'} active {@$sortOrder}{/if}"><a href="{link application='chat' controller='ChatSuspensionList'}pageNo={@$pageNo}&sortField=issuer&sortOrder={if $sortField == 'issuer' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$additionalParameters}{/link}">{lang}chat.acp.suspension.issuer{/lang}</a></th>
|
||||||
|
<th class="columnMessage{if $sortField == 'reason'} active {@$sortOrder}{/if}"><a href="{link application='chat' controller='ChatSuspensionList'}pageNo={@$pageNo}&sortField=reason&sortOrder={if $sortField == 'reason' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$additionalParameters}{/link}">{lang}chat.acp.suspension.reason{/lang}</a></th>
|
||||||
|
|
||||||
|
{event name='columnHeads'}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{foreach from=$objects item=$suspension}
|
||||||
|
<tr class="jsSuspensionRow" data-object-id="{$suspension->suspensionID}">
|
||||||
|
<td class="columnIcon">
|
||||||
|
<span class="icon icon16 icon-undo{if $suspension->expires <= TIME_NOW} disabled{else} pointer{/if} jsRevokeButton" title="{lang}chat.acp.suspension.revoke{/lang}" data-confirm-message="{lang}chat.acp.suspension.revoke.sure{/lang}"></span>
|
||||||
|
{event name='rowButtons'}
|
||||||
|
</td>
|
||||||
|
<td id="columnID">{#$suspension->suspensionID}</td>
|
||||||
|
<td id="columnUsername"><a href="{link application='chat' controller='ChatSuspensionList'}userID={$suspension->userID}{/link}">{$suspension->username}</a></td>
|
||||||
|
<td id="columnRoomID"><a href="{link application='chat' controller='ChatSuspensionList'}roomID={if $suspension->roomID}{$suspension->roomID}{else}0{/if}{/link}">{if $suspension->roomID}{$suspension->roomTitle|language}{else}{lang}chat.room.global{/lang}{/if}</a></td>
|
||||||
|
<td id="columnSuspensionType"><a href="{link application='chat' controller='ChatSuspensionList'}suspensionType={$suspension->type}{/link}">{lang}chat.suspension.{@$suspension->type}{/lang}</a></td>
|
||||||
|
<td id="columnTime">{$suspension->time|plainTime}</td>
|
||||||
|
<td id="columnExpires">
|
||||||
|
<p>{$suspension->expires|plainTime}{if $suspension->expires > TIME_NOW} ({$suspension->expires|dateDiff}){/if}</p>
|
||||||
|
{if $suspension->revoker && $suspension->expires <= TIME_NOW}<p><small>{lang}chat.acp.suspension.revokedBy{/lang}</small></p>{/if}
|
||||||
|
</td>
|
||||||
|
<td id="columnIssuer"><a href="{link application='chat' controller='ChatSuspensionList'}issuerUserID={$suspension->issuer}{/link}">{$suspension->issuerUsername}</a></td>
|
||||||
|
<td id="columnMessage"{if $suspension->reason != $suspension->reason|truncate:30} class="jsTooltip" title="{$suspension->reason}"{/if}>{$suspension->reason|truncate:30}</a></td>
|
||||||
|
{event name='columns'}
|
||||||
|
</tr>
|
||||||
|
{/foreach}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="contentNavigation">
|
||||||
|
{@$pagesLinks}
|
||||||
|
</div>
|
||||||
|
{else}
|
||||||
|
<p class="info">{lang}wcf.global.noItems{/lang}</p>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{include file='footer'}
|
109
acptemplate/messageLog.tpl
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
{include file='header' pageTitle='chat.acp.log.title'}
|
||||||
|
|
||||||
|
{if CHAT_LOG_ARCHIVETIME !== 0}
|
||||||
|
<script data-relocate="true" src="{$__wcf->getPath('chat')}acp/js/be.bastelstu.Chat.ACP.Log.js?version={PACKAGE_VERSION|rawurlencode}"></script>
|
||||||
|
|
||||||
|
{if $errorField === ''}
|
||||||
|
<script data-relocate="true">
|
||||||
|
//<![CDATA[
|
||||||
|
$(function() {
|
||||||
|
be.bastelstu.Chat.ACP.Log.TabMenu.init();
|
||||||
|
WCF.TabMenu.init();
|
||||||
|
});
|
||||||
|
//]]>
|
||||||
|
</script>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<header class="boxHeadline">
|
||||||
|
<h1>{lang}{@$pageTitle}{/lang}</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{if CHAT_LOG_ARCHIVETIME !== 0}
|
||||||
|
<form method="post" action="{link controller='MessageLog' application='chat'}{/link}">
|
||||||
|
<div class="container containerPadding marginTop">
|
||||||
|
<fieldset>
|
||||||
|
<legend>{lang}wcf.global.filter{/lang}</legend>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt><label for="id">{lang}chat.global.room{/lang}</label></dt>
|
||||||
|
<dd>
|
||||||
|
<select id="id" name="id">
|
||||||
|
{foreach from=$rooms item='roomBit'}
|
||||||
|
<option value="{$roomBit->roomID}"{if $roomBit->roomID == $room->roomID} selected="selected"{/if}>{$roomBit}</option>
|
||||||
|
{/foreach}
|
||||||
|
</select>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl{if $errorField == 'date'} class="formError"{/if}>
|
||||||
|
<dt><label for="date">{lang}chat.global.time{/lang}</label></dt>
|
||||||
|
<dd>
|
||||||
|
<input id="date" type="date" name="date"{if CHAT_LOG_ARCHIVETIME != -1} min="{TIME_NOW-CHAT_LOG_ARCHIVETIME*60|date:'Y-m-d'}"{/if} max="{TIME_NOW|date:'Y-m-d'}" value="{$date|date:'Y-m-d'}" />
|
||||||
|
{if $errorField == 'date'}
|
||||||
|
<small class="innerError">
|
||||||
|
{lang}chat.acp.log.date.error.{$errorType}{/lang}
|
||||||
|
</small>
|
||||||
|
{/if}
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="formSubmit">
|
||||||
|
<input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="contentNavigation">
|
||||||
|
<nav>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a class="button" href="{link controller='MessageLogDownload' application='chat' object=$room date=$date|date:'Y-m-d'}{/link}">
|
||||||
|
<span class="icon icon16 icon-download-alt"></span>
|
||||||
|
<span>{lang}chat.acp.log.download{/lang}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{if $errorField === ''}
|
||||||
|
<div id="messageLogContent" class="tabMenuContainer marginTop" data-active="timeTab-0" data-store="activeTabMenuItem" data-base-time="{$date}" data-room-id="{$room->roomID}">
|
||||||
|
<nav class="tabMenu">
|
||||||
|
<ul>
|
||||||
|
{section name=tabLoop loop=24 step=3}
|
||||||
|
<li>
|
||||||
|
{assign var=anchor value='timeTab-'|concat:$tabLoop}
|
||||||
|
<a href="{@$__wcf->getAnchor($anchor)}">{if $tabLoop < 10}0{/if}{$tabLoop}:00 - {if $tabLoop + 2 < 10}0{/if}{$tabLoop + 2}:59</a>
|
||||||
|
</li>
|
||||||
|
{/section}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{section name=contentLoop loop=24 step=3}
|
||||||
|
<div id="timeTab-{$contentLoop}" class="container containerPadding tabMenuContainer tabMenuContent" data-menu-item="timeTab-{$contentLoop}">
|
||||||
|
<nav class="menu">
|
||||||
|
<ul>
|
||||||
|
{section name=subTabLoop loop=6}
|
||||||
|
{assign var=subAnchor value='timeTab-'|concat:$contentLoop|concat:'-subTab-'|concat:$subTabLoop}
|
||||||
|
<li data-hour="{$contentLoop + $subTabLoop / 2|floor}" data-minutes="{($subTabLoop % 2) * 30}">
|
||||||
|
<a href="{@$__wcf->getAnchor($subAnchor)}">{if $contentLoop + $subTabLoop / 2 < 10}0{/if}{$contentLoop + $subTabLoop / 2|floor}:{if $subTabLoop % 2 == 0}0{/if}{($subTabLoop % 2) * 30} - {if $contentLoop + $subTabLoop / 2 < 10}0{/if}{$contentLoop + $subTabLoop / 2|floor}:{($subTabLoop % 2) * 30 + 29}</a>
|
||||||
|
</li>
|
||||||
|
{/section}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{section name=subTabLoop loop=6}
|
||||||
|
{assign var=subAnchor value='timeTab-'|concat:$contentLoop|concat:'-subTab-'|concat:$subTabLoop}
|
||||||
|
<div id="{$subAnchor}" class="hidden subTabMenuContent empty"></div>
|
||||||
|
{/section}
|
||||||
|
</div>
|
||||||
|
{/section}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{else}
|
||||||
|
<p class="error">{lang}chat.acp.log.error.disabled{/lang}</p>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{include file='footer'}
|
5
acptemplate/messageLogDownload.tpl
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{foreach from=$messages item=$rawMessage}{*
|
||||||
|
*}{assign var=message value=$rawMessage->jsonify(true)}{*
|
||||||
|
*}({$message['time']|date:'H:i:s'}) {$message[username]|str_pad:15:' ':STR_PAD_LEFT}{$message[separator]} {$message[message]}
|
||||||
|
|
||||||
|
{/foreach}
|
87
acptemplate/roomAdd.tpl
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
{include file='header' pageTitle='chat.acp.room.'|concat:$action}
|
||||||
|
|
||||||
|
{include file='aclPermissions'}
|
||||||
|
{if !$roomID|isset}
|
||||||
|
{include file='aclPermissionJavaScript' containerID='groupPermissions'}
|
||||||
|
{else}
|
||||||
|
{include file='aclPermissionJavaScript' containerID='groupPermissions' objectID=$roomID}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<header class="boxHeadline">
|
||||||
|
<h1>{lang}chat.acp.room.{$action}{/lang}</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{include file='formError'}
|
||||||
|
|
||||||
|
{if $success|isset}
|
||||||
|
<p class="success">{lang}wcf.global.success.{$action}{/lang}</p>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div class="contentNavigation">
|
||||||
|
{hascontent}
|
||||||
|
<nav>
|
||||||
|
<ul>
|
||||||
|
{content}
|
||||||
|
<li><a href="{link application='chat' controller='RoomList'}{/link}" class="button"><span class="icon icon16 icon-list"></span> <span>{lang}chat.acp.menu.link.room.list{/lang}</span></a></li>
|
||||||
|
{event name='contentNavigationButtonsTop'}
|
||||||
|
{/content}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
{/hascontent}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="post" action="{if $action == 'add'}{link application='chat' controller='RoomAdd'}{/link}{else}{link application='chat' controller='RoomEdit' id=$roomID}{/link}{/if}">
|
||||||
|
<div class="container containerPadding marginTop">
|
||||||
|
<fieldset>
|
||||||
|
<legend>{lang}wcf.global.form.data{/lang}</legend>
|
||||||
|
|
||||||
|
<dl{if $errorField == 'title'} class="formError"{/if}>
|
||||||
|
<dt><label for="title">{lang}chat.acp.room.title{/lang}</label></dt>
|
||||||
|
<dd>
|
||||||
|
<input type="text" id="title" name="title" value="{$title}" autofocus="autofocus" class="long" />
|
||||||
|
{if $errorField == 'title'}
|
||||||
|
<small class="innerError">
|
||||||
|
{if $errorType == 'empty'}
|
||||||
|
{lang}wcf.global.form.error.empty{/lang}
|
||||||
|
{else}
|
||||||
|
{lang}chat.acp.room.title.error.{@$errorType}{/lang}
|
||||||
|
{/if}
|
||||||
|
</small>
|
||||||
|
{/if}
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
{include file='multipleLanguageInputJavascript' elementIdentifier='title' forceSelection=false}
|
||||||
|
|
||||||
|
<dl{if $errorField == 'topic'} class="formError"{/if}>
|
||||||
|
<dt><label for="topic">{lang}chat.acp.room.topic{/lang}</label></dt>
|
||||||
|
<dd>
|
||||||
|
<input type="text" id="topic" name="topic" value="{$topic}" class="long" />
|
||||||
|
{if $errorField == 'topic'}
|
||||||
|
<small class="innerError">
|
||||||
|
{if $errorType == 'empty'}
|
||||||
|
{lang}wcf.global.form.error.empty{/lang}
|
||||||
|
{else}
|
||||||
|
{lang}chat.acp.room.topic.error.{@$errorType}{/lang}
|
||||||
|
{/if}
|
||||||
|
</small>
|
||||||
|
{/if}
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
{include file='multipleLanguageInputJavascript' elementIdentifier='topic' forceSelection=false}
|
||||||
|
|
||||||
|
<dl id="groupPermissions">
|
||||||
|
<dt>{lang}wcf.acl.permissions{/lang}</dt>
|
||||||
|
<dd></dd>
|
||||||
|
</dl>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="formSubmit">
|
||||||
|
<input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s" />
|
||||||
|
{@SECURITY_TOKEN_INPUT_TAG}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{include file='footer'}
|
66
acptemplate/roomList.tpl
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
{include file='header' pageTitle='chat.acp.room.list'}
|
||||||
|
|
||||||
|
<script data-relocate="true">
|
||||||
|
//<![CDATA[
|
||||||
|
$(function() {
|
||||||
|
new WCF.Action.Delete('\\chat\\data\\room\\RoomAction', $('.chatRoomRow'));
|
||||||
|
new WCF.Sortable.List('roomList', '\\chat\\data\\room\\RoomAction');
|
||||||
|
});
|
||||||
|
//]]>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<header class="boxHeadline">
|
||||||
|
<h1>{lang}chat.acp.room.list{/lang}</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="contentNavigation">
|
||||||
|
{hascontent}
|
||||||
|
<nav>
|
||||||
|
<ul>
|
||||||
|
{content}
|
||||||
|
{if $__wcf->session->getPermission('admin.chat.canAddRoom')}
|
||||||
|
<li><a href="{link application='chat' controller='RoomAdd'}{/link}" class="button"><span class="icon icon16 icon-plus"></span> <span>{lang}chat.acp.room.add{/lang}</span></a></li>
|
||||||
|
{/if}
|
||||||
|
{event name='contentNavigationButtonsTop'}
|
||||||
|
{/content}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
{/hascontent}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{if $objects|count}
|
||||||
|
<section id="roomList" class="container containerPadding sortableListContainer marginTop">
|
||||||
|
<ol class="sortableList" data-object-id="0">
|
||||||
|
{foreach from=$objects item=chatRoom}
|
||||||
|
<li class="sortableNode sortableNoNesting chatRoomRow" data-object-id="{@$chatRoom->roomID}">
|
||||||
|
<span class="sortableNodeLabel">
|
||||||
|
{if $__wcf->session->getPermission('admin.chat.canEditRoom')}
|
||||||
|
<a href="{link application='chat' controller='RoomEdit' id=$chatRoom->roomID}{/link}">{$chatRoom->title|language}</a>
|
||||||
|
{else}
|
||||||
|
{$chatRoom->title|language}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<span class="statusDisplay sortableButtonContainer">
|
||||||
|
{if $__wcf->session->getPermission('admin.chat.canEditRoom')}
|
||||||
|
<a href="{link application='chat' controller='RoomEdit' id=$chatRoom->roomID}{/link}"><span title="{lang}wcf.global.button.edit{/lang}" class="jsTooltip icon icon16 icon-pencil" /></a>
|
||||||
|
{/if}
|
||||||
|
{if $__wcf->session->getPermission('admin.chat.canDeleteRoom')}
|
||||||
|
<span title="{lang}wcf.global.button.delete{/lang}" class="jsDeleteButton jsTooltip icon icon16 icon-remove" data-object-id="{@$chatRoom->roomID}" data-confirm-message="{lang}chat.acp.room.delete.sure{/lang}" />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{event name='itemButtons'}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<ol class="sortableList" data-object-id="{@$chatRoom->roomID}"></ol></li>
|
||||||
|
</li>
|
||||||
|
{/foreach}
|
||||||
|
</ol>
|
||||||
|
<div class="formSubmit">
|
||||||
|
<button class="button buttonPrimary" data-type="submit">{lang}wcf.global.button.saveSorting{/lang}</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{else}
|
||||||
|
<p class="warning">{lang}wcf.global.noItems{/lang}</p>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{include file='footer'}
|
@ -1,68 +0,0 @@
|
|||||||
{include file='header' pageTitle='chat.acp.command.trigger.'|concat:$action}
|
|
||||||
|
|
||||||
<header class="contentHeader">
|
|
||||||
<div class="contentHeaderTitle">
|
|
||||||
<h1 class="contentTitle">{lang}chat.acp.command.trigger.{$action}{/lang}</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<nav class="contentHeaderNavigation">
|
|
||||||
<ul>
|
|
||||||
<li><a href="{link application='chat' controller='CommandTriggerList'}{/link}" class="button">{icon name='list'} <span>{lang}chat.acp.command.trigger.list{/lang}</span></a></li>
|
|
||||||
|
|
||||||
{event name='contentHeaderNavigation'}
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
{include file='formNotice'}
|
|
||||||
|
|
||||||
<form method="post" action="{if $action == 'add'}{link application='chat' controller='CommandTriggerAdd'}{/link}{else}{link application='chat' controller='CommandTriggerEdit' id=$triggerID}{/link}{/if}">
|
|
||||||
<div class="section">
|
|
||||||
<div class="section">
|
|
||||||
<dl{if $errorField == 'commandTrigger'} class="formError"{/if}>
|
|
||||||
<dt><label for="commandTrigger">{lang}chat.acp.command.trigger{/lang}</label></dt>
|
|
||||||
<dd>
|
|
||||||
<input type="text" id="commandTrigger" name="commandTrigger" value="{$commandTrigger}" autofocus class="medium">
|
|
||||||
{if $errorField == 'commandTrigger'}
|
|
||||||
<small class="innerError">
|
|
||||||
{if $errorType == 'empty'}
|
|
||||||
{lang}wcf.global.form.error.empty{/lang}
|
|
||||||
{else}
|
|
||||||
{lang}chat.acp.command.trigger.commandTrigger.error.{@$errorType}{/lang}
|
|
||||||
{/if}
|
|
||||||
</small>
|
|
||||||
{/if}
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dl{if $errorField == 'className'} class="formError"{/if}>
|
|
||||||
<dt><label for="className">{lang}chat.acp.command.className{/lang}</label></dt>
|
|
||||||
<dd>
|
|
||||||
<select id="className" name="className">
|
|
||||||
{foreach from=$availableCommands item=$command}
|
|
||||||
<option value="{$command->className}"{if $command->className === $className} selected{/if}>{$command->className}</option>
|
|
||||||
{/foreach}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
{if $errorField == 'className'}
|
|
||||||
<small class="innerError">
|
|
||||||
{if $errorType == 'empty'}
|
|
||||||
{lang}wcf.global.form.error.empty{/lang}
|
|
||||||
{else}
|
|
||||||
{lang}chat.acp.command.trigger.className.error.{@$errorType}{/lang}
|
|
||||||
{/if}
|
|
||||||
</small>
|
|
||||||
{/if}
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="formSubmit">
|
|
||||||
<input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s">
|
|
||||||
{csrfToken}
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{include file='footer'}
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
|||||||
{include file='header' pageTitle='chat.acp.command.trigger.list'}
|
|
||||||
|
|
||||||
<script data-relocate="true">
|
|
||||||
$(function() {
|
|
||||||
new WCF.Action.Delete('chat\\data\\command\\CommandTriggerAction', '.jsTriggerRow');
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<header class="contentHeader">
|
|
||||||
<div class="contentHeaderTitle">
|
|
||||||
<h1 class="contentTitle">{lang}chat.acp.command.trigger.list{/lang}</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<nav class="contentHeaderNavigation">
|
|
||||||
<ul>
|
|
||||||
<li><a href="{link controller='CommandTriggerAdd' application='chat'}{/link}" class="button">{icon name='plus'} <span>{lang}chat.acp.command.trigger.add{/lang}</span></a></li>
|
|
||||||
|
|
||||||
{event name='contentHeaderNavigation'}
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
{hascontent}
|
|
||||||
<div class="paginationTop">
|
|
||||||
{content}{pages print=true assign=pagesLinks controller="CommandTriggerList" application="chat" link="pageNo=%d&sortField=$sortField&sortOrder=$sortOrder"}{/content}
|
|
||||||
</div>
|
|
||||||
{/hascontent}
|
|
||||||
|
|
||||||
{hascontent}
|
|
||||||
<div class="section tabularBox">
|
|
||||||
<table class="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="columnID columnTriggerID{if $sortField == 'triggerID'} active {@$sortOrder}{/if}" colspan="2"><a href="{link controller='CommandTriggerList' application='chat'}pageNo={@$pageNo}&sortField=triggerID&sortOrder={if $sortField == 'triggerID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}wcf.global.objectID{/lang}</a></th>
|
|
||||||
<th class="columnTitle columnTrigger{if $sortField == 'commandTrigger'} active {@$sortOrder}{/if}"><a href="{link controller='CommandTriggerList' application='chat'}pageNo={@$pageNo}&sortField=commandTrigger&sortOrder={if $sortField == 'commandTrigger' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}chat.acp.command.trigger{/lang}</a></th>
|
|
||||||
<th class="columnText columnClassName{if $sortField == 'className'} active {@$sortOrder}{/if}"><a href="{link controller='CommandTriggerList' application='chat'}pageNo={@$pageNo}&sortField=className&sortOrder={if $sortField == 'className' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}chat.acp.command.className{/lang}</a></th>
|
|
||||||
|
|
||||||
{event name='columnHeads'}
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
|
|
||||||
<tbody>
|
|
||||||
{content}
|
|
||||||
{foreach from=$objects item=trigger}
|
|
||||||
<tr class="jsTriggerRow">
|
|
||||||
<td class="columnIcon">
|
|
||||||
<a href="{link controller='CommandTriggerEdit' object=$trigger application='chat'}{/link}" title="{lang}wcf.global.button.edit{/lang}" class="jsTooltip">{icon name='pencil'}</a>
|
|
||||||
<span class="jsDeleteButton jsTooltip pointer" title="{lang}wcf.global.button.delete{/lang}" data-object-id="{$trigger->triggerID}" data-confirm-message-html="{lang __encode=true}chat.acp.command.trigger.delete.sure{/lang}">{icon name='xmark'}</span>
|
|
||||||
|
|
||||||
{event name='rowButtons'}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="columnID">{@$trigger->triggerID}</td>
|
|
||||||
<td class="columnTitle columnTrigger"><a href="{link controller='CommandTriggerEdit' object=$trigger application='chat'}{/link}">/{$trigger->commandTrigger}</a></td>
|
|
||||||
<td class="columnText columnClassName">{$trigger->className}</td>
|
|
||||||
|
|
||||||
{event name='columns'}
|
|
||||||
</tr>
|
|
||||||
{/foreach}
|
|
||||||
{/content}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{hascontentelse}
|
|
||||||
<p class="info">{lang}wcf.global.noItems{/lang}</p>
|
|
||||||
{/hascontent}
|
|
||||||
|
|
||||||
<footer class="contentFooter">
|
|
||||||
{hascontent}
|
|
||||||
<div class="paginationBottom">
|
|
||||||
{content}{@$pagesLinks}{/content}
|
|
||||||
</div>
|
|
||||||
{/hascontent}
|
|
||||||
|
|
||||||
<nav class="contentFooterNavigation">
|
|
||||||
<ul>
|
|
||||||
<li><a href="{link controller='CommandTriggerAdd' application='chat'}{/link}" class="button">{icon name='plus'} <span>{lang}chat.acp.command.trigger.add{/lang}</span></a></li>
|
|
||||||
|
|
||||||
{event name='contentFooterNavigation'}
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
{include file='footer'}
|
|
||||||
|
|
@ -1,109 +0,0 @@
|
|||||||
{include file='header' pageTitle='chat.acp.room.'|concat:$action}
|
|
||||||
|
|
||||||
{include file='aclPermissions'}
|
|
||||||
|
|
||||||
{include file='multipleLanguageInputJavascript' elementIdentifier='title' forceSelection=false}
|
|
||||||
{include file='multipleLanguageInputJavascript' elementIdentifier='topic' forceSelection=false}
|
|
||||||
|
|
||||||
{if $roomID|isset}
|
|
||||||
{include file='aclPermissionJavaScript' containerID='aclContainer' objectTypeID=$aclObjectTypeID objectID=$roomID}
|
|
||||||
{else}
|
|
||||||
{include file='aclPermissionJavaScript' containerID='aclContainer' objectTypeID=$aclObjectTypeID}
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<header class="contentHeader">
|
|
||||||
<div class="contentHeaderTitle">
|
|
||||||
<h1 class="contentTitle">{lang}chat.acp.room.{$action}{/lang}</h1>
|
|
||||||
{if $action == 'edit'}<p class="contentHeaderDescription">{$room->getTitle()}</p>{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<nav class="contentHeaderNavigation">
|
|
||||||
<ul>
|
|
||||||
<li><a href="{link application='chat' controller='RoomList'}{/link}" class="button">{icon name='list'} <span>{lang}chat.acp.room.list{/lang}</span></a></li>
|
|
||||||
|
|
||||||
{event name='contentHeaderNavigation'}
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
{include file='formNotice'}
|
|
||||||
|
|
||||||
<form method="post" action="{if $action == 'add'}{link application='chat' controller='RoomAdd'}{/link}{else}{link application='chat' controller='RoomEdit' id=$roomID}{/link}{/if}">
|
|
||||||
<div class="section">
|
|
||||||
<div class="section">
|
|
||||||
<dl{if $errorField == 'title'} class="formError"{/if}>
|
|
||||||
<dt><label for="title">{lang}wcf.global.title{/lang}</label></dt>
|
|
||||||
<dd>
|
|
||||||
<input type="text" id="title" name="title" value="{$i18nPlainValues['title']}" autofocus class="medium">
|
|
||||||
{if $errorField == 'title'}
|
|
||||||
<small class="innerError">
|
|
||||||
{if $errorType == 'empty'}
|
|
||||||
{lang}wcf.global.form.error.empty{/lang}
|
|
||||||
{elseif $errorType == 'multilingual'}
|
|
||||||
{lang}wcf.global.form.error.multilingual{/lang}
|
|
||||||
{else}
|
|
||||||
{lang}chat.acp.room.title.error.{@$errorType}{/lang}
|
|
||||||
{/if}
|
|
||||||
</small>
|
|
||||||
{/if}
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dl{if $errorField == 'topic'} class="formError"{/if}>
|
|
||||||
<dt><label for="topic">{lang}chat.acp.room.topic{/lang}</label></dt>
|
|
||||||
<dd>
|
|
||||||
<input type="text" id="topic" name="topic" value="{$i18nPlainValues['topic']}" class="long">
|
|
||||||
|
|
||||||
{if $errorField == 'topic'}
|
|
||||||
<small class="innerError">
|
|
||||||
{if $errorType == 'empty'}
|
|
||||||
{lang}wcf.global.form.error.empty{/lang}
|
|
||||||
{else}
|
|
||||||
{lang}chat.acp.room.topic.error.{@$errorType}{/lang}
|
|
||||||
{/if}
|
|
||||||
</small>
|
|
||||||
{/if}
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dl{if $errorField == 'topicUseHtml'} class="formError"{/if}>
|
|
||||||
<dt></dt>
|
|
||||||
<dd>
|
|
||||||
<label><input type="checkbox" name="topicUseHtml" value="1"{if $topicUseHtml} checked{/if}> {lang}chat.acp.room.topicUseHtml{/lang}</label>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dl{if $errorField == 'userLimit'} class="formError"{/if}>
|
|
||||||
<dt><label for="userLimit">{lang}chat.acp.room.userLimit{/lang}</label></dt>
|
|
||||||
<dd>
|
|
||||||
<input type="number" id="userLimit" name="userLimit" value="{$userLimit}" min="0" class="medium">
|
|
||||||
|
|
||||||
{if $errorField == 'userLimit'}
|
|
||||||
<small class="innerError">
|
|
||||||
{if $errorType == 'empty'}
|
|
||||||
{lang}wcf.global.form.error.empty{/lang}
|
|
||||||
{else}
|
|
||||||
{lang}chat.acp.room.userLimit.error.{@$errorType}{/lang}
|
|
||||||
{/if}
|
|
||||||
</small>
|
|
||||||
{/if}
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section">
|
|
||||||
<dl id="aclContainer">
|
|
||||||
<dt>{lang}wcf.acl.permissions{/lang}</dt>
|
|
||||||
<dd></dd>
|
|
||||||
</dl>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="formSubmit">
|
|
||||||
<input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s">
|
|
||||||
{csrfToken}
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{include file='footer'}
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
|||||||
{include file='header' pageTitle='chat.acp.room.list'}
|
|
||||||
|
|
||||||
<script data-relocate="true">
|
|
||||||
$(function() {
|
|
||||||
require([ 'WoltLabSuite/Core/Ui/Sortable/List' ], function (UiSortableList) {
|
|
||||||
new UiSortableList({ containerId: 'roomNodeList'
|
|
||||||
, className: 'chat\\data\\room\\RoomAction'
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
new WCF.Action.Delete('chat\\data\\room\\RoomAction', '#roomNodeList')
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<header class="contentHeader">
|
|
||||||
<div class="contentHeaderTitle">
|
|
||||||
<h1 class="contentTitle">{lang}chat.acp.room.list{/lang}</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<nav class="contentHeaderNavigation">
|
|
||||||
<ul>
|
|
||||||
<li><a href="{link controller='RoomAdd' application='chat'}{/link}" class="button">{icon name='plus'} <span>{lang}chat.acp.room.add{/lang}</span></a></li>
|
|
||||||
|
|
||||||
{event name='contentHeaderNavigation'}
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
{hascontent}
|
|
||||||
<div class="paginationTop">
|
|
||||||
{content}{pages print=true assign=pagesLinks controller="RoomList" application="chat" link="pageNo=%d&sortField=$sortField&sortOrder=$sortOrder"}{/content}
|
|
||||||
</div>
|
|
||||||
{/hascontent}
|
|
||||||
|
|
||||||
{hascontent}
|
|
||||||
<div id="roomNodeList" class="section sortableListContainer">
|
|
||||||
<ol id="roomContainer0" class="sortableList" data-object-id="0">
|
|
||||||
{content}
|
|
||||||
{foreach from=$objects item=room}
|
|
||||||
<li class="sortableNode sortableNoNesting" data-object-id="{$room->roomID}">
|
|
||||||
<span class="sortableNodeLabel">
|
|
||||||
<a href="{link controller='RoomEdit' application='chat' object=$room}{/link}">{$room}</a>
|
|
||||||
|
|
||||||
<span class="statusDisplay sortableButtonContainer">
|
|
||||||
<span class="sortableNodeHandle">{icon name='up-down-left-right'}</span>
|
|
||||||
<a href="{link controller='RoomEdit' application='chat' object=$room}{/link}" title="{lang}wcf.global.button.edit{/lang}" class="jsTooltip">{icon name='pencil'}</a>
|
|
||||||
<span class="jsDeleteButton jsTooltip pointer" title="{lang}wcf.global.button.delete{/lang}" data-object-id="{$room->roomID}" data-confirm-message-html="{lang __encode=true}chat.acp.room.delete.sure{/lang}">{icon name='xmark'}</span>
|
|
||||||
{event name='itemButtons'}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
{/foreach}
|
|
||||||
{/content}
|
|
||||||
</ol>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="formSubmit">
|
|
||||||
<button class="button buttonPrimary" data-type="submit">{lang}wcf.global.button.saveSorting{/lang}</button>
|
|
||||||
</div>
|
|
||||||
{hascontentelse}
|
|
||||||
<p class="info">{lang}wcf.global.noItems{/lang}</p>
|
|
||||||
{/hascontent}
|
|
||||||
|
|
||||||
<footer class="contentFooter">
|
|
||||||
{hascontent}
|
|
||||||
<div class="paginationBottom">
|
|
||||||
{content}{@$pagesLinks}{/content}
|
|
||||||
</div>
|
|
||||||
{/hascontent}
|
|
||||||
|
|
||||||
<nav class="contentFooterNavigation">
|
|
||||||
<ul>
|
|
||||||
<li><a href="{link controller='RoomAdd' application='chat'}{/link}" class="button">{icon name='plus'} <span>{lang}chat.acp.room.add{/lang}</span></a></li>
|
|
||||||
|
|
||||||
{event name='contentFooterNavigation'}
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
{include file='footer'}
|
|
||||||
|
|
@ -1,192 +0,0 @@
|
|||||||
{include file='header' pageTitle='chat.acp.suspension.list'}
|
|
||||||
|
|
||||||
<script>
|
|
||||||
require([ 'Bastelstu.be/PromiseWrap/Ajax', 'Bastelstu.be/PromiseWrap/Ui/Confirmation', 'WoltLabSuite/Core/Dom/Traverse' ], function (Ajax, Confirmation, Traverse) {
|
|
||||||
elBySelAll('.jsRevokeButton:not(.disabled)', document, function (button) {
|
|
||||||
const row = Traverse.parentByClass(button, 'jsSuspensionRow')
|
|
||||||
if (row == null) {
|
|
||||||
throw new Error('Unreachable')
|
|
||||||
}
|
|
||||||
const objectID = row.dataset.objectId
|
|
||||||
const listener = function (event) {
|
|
||||||
Confirmation.show({
|
|
||||||
message: button.dataset.confirmMessageHtml,
|
|
||||||
messageIsHtml: true
|
|
||||||
}).then(function () {
|
|
||||||
const payload = { data: { className: 'chat\\data\\suspension\\SuspensionAction'
|
|
||||||
, actionName: 'revoke'
|
|
||||||
, objectIDs: [ objectID ]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Ajax.apiOnce(payload)
|
|
||||||
}).then(function () {
|
|
||||||
button.classList.remove('pointer')
|
|
||||||
button.classList.add('disabled')
|
|
||||||
button.removeEventListener('click', listener)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
button.addEventListener('click', listener)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<header class="contentHeader">
|
|
||||||
<div class="contentHeaderTitle">
|
|
||||||
<h1 class="contentTitle">{lang}chat.acp.suspension.list{/lang}</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{hascontent}
|
|
||||||
<nav class="contentHeaderNavigation">
|
|
||||||
<ul>
|
|
||||||
{content}{event name='contentHeaderNavigation'}{/content}
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
{/hascontent}
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<form method="post" action="{link controller='SuspensionList' application='chat'}{/link}">
|
|
||||||
<section class="section">
|
|
||||||
<h2 class="sectionTitle">{lang}wcf.global.filter{/lang}</h2>
|
|
||||||
|
|
||||||
<div class="row rowColGap formGrid">
|
|
||||||
<dl class="col-xs-12 col-md-4">
|
|
||||||
<dt></dt>
|
|
||||||
<dd>
|
|
||||||
<select name="roomID" id="roomID">
|
|
||||||
<option value=""{if $roomID === null} selected{/if}>{lang}chat.acp.suspension.room.all{/lang}</option>
|
|
||||||
<option value="0"{if $roomID === 0} selected{/if}>{lang}chat.acp.suspension.room.global{/lang}</option>
|
|
||||||
{htmlOptions options=$availableRooms selected=$roomID}
|
|
||||||
</select>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dl class="col-xs-12 col-md-4">
|
|
||||||
<dt></dt>
|
|
||||||
<dd>
|
|
||||||
<select name="objectTypeID" id="objectTypeID">
|
|
||||||
<option value="">{lang}chat.acp.suspension.objectType.allTypes{/lang}</option>
|
|
||||||
{foreach from=$availableObjectTypes item=availableObjectType}
|
|
||||||
<option value="{$availableObjectType->objectTypeID}"{if $availableObjectType->objectTypeID == $objectTypeID} selected{/if}>{lang}chat.acp.suspension.type.{$availableObjectType->objectType}{/lang}</option>
|
|
||||||
{/foreach}
|
|
||||||
</select>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dl class="col-xs-12 col-md-4">
|
|
||||||
<dt></dt>
|
|
||||||
<dd>
|
|
||||||
<input type="text" id="searchUsername" name="searchUsername" value="{$searchUsername}" placeholder="{lang}chat.acp.suspension.username{/lang}" class="long">
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
|
|
||||||
<dl class="col-xs-12 col-md-4">
|
|
||||||
<dt></dt>
|
|
||||||
<dd>
|
|
||||||
<input type="text" id="searchJudge" name="searchJudge" value="{$searchJudge}" placeholder="{lang}chat.acp.suspension.judge{/lang}" class="long">
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dl class="col-xs-12 col-md-4">
|
|
||||||
<dt></dt>
|
|
||||||
<dd>
|
|
||||||
<label><input name="showExpired" value="1" type="checkbox"{if $showExpired !== false} checked{/if}>{lang}chat.acp.suspension.showExpired{/lang}</label>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
{event name='filterFields'}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="formSubmit">
|
|
||||||
<input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s">
|
|
||||||
{csrfToken}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
{capture assign=additionalParameters}{*
|
|
||||||
*}{if $userID !== null}&userID={$userID}{/if}{*
|
|
||||||
*}{if $judgeID !== null}&judgeID={$judgeID}{/if}{*
|
|
||||||
*}{if $roomID !== null}&roomID={$roomID}{/if}{*
|
|
||||||
*}{if $objectTypeID !== null}&objectTypeID={$objectTypeID}{/if}{*
|
|
||||||
*}{if $showExpired !== null}&showExpired={$showExpired}{/if}{*
|
|
||||||
*}{/capture}
|
|
||||||
|
|
||||||
{hascontent}
|
|
||||||
<div class="paginationTop">
|
|
||||||
{content}{pages print=true assign=pagesLinks controller="SuspensionList" application="chat" link="pageNo=%d&sortField=$sortField&sortOrder=$sortOrder$additionalParameters"}{/content}
|
|
||||||
</div>
|
|
||||||
{/hascontent}
|
|
||||||
|
|
||||||
{hascontent}
|
|
||||||
<div class="section tabularBox">
|
|
||||||
<table class="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="columnID columnSuspensionID{if $sortField == 'suspensionID'} active {@$sortOrder}{/if}" colspan="2"><a href="{link controller='SuspensionList' application='chat'}pageNo={@$pageNo}&sortField=suspensionID&sortOrder={if $sortField == 'suspensionID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$additionalParameters}{/link}">{lang}wcf.global.objectID{/lang}</a></th>
|
|
||||||
<th class="columnTitle columnObjectType">{lang}chat.acp.suspension.type{/lang}</th>
|
|
||||||
<th class="columnText columnUsername">{lang}chat.acp.suspension.username{/lang}</th>
|
|
||||||
<th class="columnText columnJudge">{lang}chat.acp.suspension.judge{/lang}</th>
|
|
||||||
<th class="columnText columnRoom">{lang}chat.acp.suspension.room{/lang}</th>
|
|
||||||
<th class="columnText columnTime{if $sortField == 'time'} active {@$sortOrder}{/if}"><a href="{link controller='SuspensionList' application='chat'}pageNo={@$pageNo}&sortField=time&sortOrder={if $sortField == 'time' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$additionalParameters}{/link}">{lang}chat.acp.suspension.time{/lang}</a></th>
|
|
||||||
<th class="columnText columnExpires{if $sortField == 'expiresSort'} active {@$sortOrder}{/if}"><a href="{link controller='SuspensionList' application='chat'}pageNo={@$pageNo}&sortField=expiresSort&sortOrder={if $sortField == 'expiresSort' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$additionalParameters}{/link}">{lang}chat.acp.suspension.expires{/lang}</a></th>
|
|
||||||
|
|
||||||
{event name='columnHeads'}
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
|
|
||||||
<tbody>
|
|
||||||
{content}
|
|
||||||
{foreach from=$objects item=suspension}
|
|
||||||
<tr class="jsSuspensionRow" data-object-id="{$suspension->suspensionID}">
|
|
||||||
<td class="columnIcon">
|
|
||||||
<span class="jsRevokeButton{if !$suspension->isActive()} disabled{else} pointer{/if}" title="{lang}chat.acp.suspension.revoke{/lang}" data-confirm-message-html="{lang}chat.acp.suspension.revoke.sure{/lang}">{icon name='arrow-rotate-left'}</span>
|
|
||||||
{event name='rowButtons'}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="columnID">{@$suspension->suspensionID}</td>
|
|
||||||
<td class="columnTitle columnObjectType"><a href="{link controller="SuspensionList" application="chat"}objectTypeID={$suspension->objectTypeID}{/link}">{lang}chat.acp.suspension.type.{$suspension->getSuspensionType()->objectType}{/lang}</a></td>
|
|
||||||
<td class="columnText columnUsername"><a href="{link controller="SuspensionList" application="chat"}userID={$suspension->userID}{/link}">{$suspension->getUser()->username}</a></td>
|
|
||||||
<td class="columnText columnJudge"><a href="{link controller="SuspensionList" application="chat"}judgeID={$suspension->judgeID}{/link}">{$suspension->judge}</a></td>
|
|
||||||
<td class="columnText columnRoom"><a href="{link controller="SuspensionList" application="chat"}roomID={$suspension->roomID}{/link}">{if $suspension->getRoom() !== null}{$suspension->getRoom()}{else}-{/if}</a></td>
|
|
||||||
<td class="columnText columnTime">{@$suspension->time|time}</td>
|
|
||||||
<td class="columnText columnExpires">
|
|
||||||
{assign var='isActive' value=$suspension->isActive()}
|
|
||||||
{if $isActive}<strong>{/if}
|
|
||||||
{if $suspension->expires !== null}{@$suspension->expires|time}{else}{lang}chat.acp.suspension.expires.forever{/lang}{/if}
|
|
||||||
{if $isActive}</strong>{/if}
|
|
||||||
{if $suspension->revoked !== null}
|
|
||||||
<br>{lang}chat.acp.suspension.revoked{/lang}
|
|
||||||
{/if}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
{event name='columns'}
|
|
||||||
</tr>
|
|
||||||
{/foreach}
|
|
||||||
{/content}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{hascontentelse}
|
|
||||||
<p class="info">{lang}wcf.global.noItems{/lang}</p>
|
|
||||||
{/hascontent}
|
|
||||||
|
|
||||||
<footer class="contentFooter">
|
|
||||||
{hascontent}
|
|
||||||
<div class="paginationBottom">
|
|
||||||
{content}{@$pagesLinks}{/content}
|
|
||||||
</div>
|
|
||||||
{/hascontent}
|
|
||||||
|
|
||||||
{hascontent}
|
|
||||||
<nav class="contentFooterNavigation">
|
|
||||||
<ul>
|
|
||||||
{content}{event name='contentFooterNavigation'}{/content}
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
{/hascontent}
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
{include file='footer'}
|
|
||||||
|
|
42
box.xml
@ -1,42 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/vortex/box.xsd">
|
|
||||||
<import>
|
|
||||||
<box identifier="be.bastelstu.chat.roomListDashboard">
|
|
||||||
<name language="de">Chaträume (Inhaltsbereich)</name>
|
|
||||||
<name language="en">Chat Rooms (Content)</name>
|
|
||||||
<boxType>system</boxType>
|
|
||||||
<objectType>be.bastelstu.chat.roomList</objectType>
|
|
||||||
<position>contentTop</position>
|
|
||||||
<showHeader>1</showHeader>
|
|
||||||
<visibleEverywhere>0</visibleEverywhere>
|
|
||||||
<visibilityExceptions>
|
|
||||||
<page>com.woltlab.wcf.Dashboard</page>
|
|
||||||
</visibilityExceptions>
|
|
||||||
<content language="de">
|
|
||||||
<title>Chaträume</title>
|
|
||||||
</content>
|
|
||||||
<content language="en">
|
|
||||||
<title>Chat Rooms</title>
|
|
||||||
</content>
|
|
||||||
</box>
|
|
||||||
|
|
||||||
<box identifier="be.bastelstu.chat.roomListSidebar">
|
|
||||||
<name language="de">Chaträume (Seitenleiste)</name>
|
|
||||||
<name language="en">Chat Rooms (Sidebar)</name>
|
|
||||||
<boxType>system</boxType>
|
|
||||||
<objectType>be.bastelstu.chat.roomList</objectType>
|
|
||||||
<position>sidebarRight</position>
|
|
||||||
<showHeader>1</showHeader>
|
|
||||||
<visibleEverywhere>0</visibleEverywhere>
|
|
||||||
<visibilityExceptions>
|
|
||||||
<page>be.bastelstu.chat.Room</page>
|
|
||||||
</visibilityExceptions>
|
|
||||||
<content language="de">
|
|
||||||
<title>Chaträume</title>
|
|
||||||
</content>
|
|
||||||
<content language="en">
|
|
||||||
<title>Chat Rooms</title>
|
|
||||||
</content>
|
|
||||||
</box>
|
|
||||||
</import>
|
|
||||||
</data>
|
|
103
chatCommand.xml
@ -1,103 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
||||||
<import>
|
|
||||||
<command name="away">
|
|
||||||
<classname>chat\system\command\AwayCommand</classname>
|
|
||||||
<triggers>
|
|
||||||
<trigger>away</trigger>
|
|
||||||
</triggers>
|
|
||||||
</command>
|
|
||||||
|
|
||||||
<command name="back">
|
|
||||||
<classname>chat\system\command\BackCommand</classname>
|
|
||||||
</command>
|
|
||||||
|
|
||||||
<command name="ban">
|
|
||||||
<classname>chat\system\command\BanCommand</classname>
|
|
||||||
<triggers>
|
|
||||||
<trigger>ban</trigger>
|
|
||||||
</triggers>
|
|
||||||
</command>
|
|
||||||
|
|
||||||
<command name="broadcast">
|
|
||||||
<classname>chat\system\command\BroadcastCommand</classname>
|
|
||||||
<triggers>
|
|
||||||
<trigger>broadcast</trigger>
|
|
||||||
</triggers>
|
|
||||||
</command>
|
|
||||||
|
|
||||||
<command name="color">
|
|
||||||
<classname>chat\system\command\ColorCommand</classname>
|
|
||||||
<triggers>
|
|
||||||
<trigger>color</trigger>
|
|
||||||
</triggers>
|
|
||||||
</command>
|
|
||||||
|
|
||||||
<command name="info">
|
|
||||||
<classname>chat\system\command\InfoCommand</classname>
|
|
||||||
<triggers>
|
|
||||||
<trigger>info</trigger>
|
|
||||||
</triggers>
|
|
||||||
</command>
|
|
||||||
|
|
||||||
<command name="me">
|
|
||||||
<classname>chat\system\command\MeCommand</classname>
|
|
||||||
<triggers>
|
|
||||||
<trigger>me</trigger>
|
|
||||||
</triggers>
|
|
||||||
</command>
|
|
||||||
|
|
||||||
<command name="mute">
|
|
||||||
<classname>chat\system\command\MuteCommand</classname>
|
|
||||||
<triggers>
|
|
||||||
<trigger>mute</trigger>
|
|
||||||
</triggers>
|
|
||||||
</command>
|
|
||||||
|
|
||||||
<command name="plain">
|
|
||||||
<classname>chat\system\command\PlainCommand</classname>
|
|
||||||
</command>
|
|
||||||
|
|
||||||
<command name="team">
|
|
||||||
<classname>chat\system\command\TeamCommand</classname>
|
|
||||||
<triggers>
|
|
||||||
<trigger>team</trigger>
|
|
||||||
</triggers>
|
|
||||||
</command>
|
|
||||||
|
|
||||||
<command name="temproom">
|
|
||||||
<classname>chat\system\command\TemproomCommand</classname>
|
|
||||||
<triggers>
|
|
||||||
<trigger>temproom</trigger>
|
|
||||||
</triggers>
|
|
||||||
</command>
|
|
||||||
|
|
||||||
<command name="unban">
|
|
||||||
<classname>chat\system\command\UnbanCommand</classname>
|
|
||||||
<triggers>
|
|
||||||
<trigger>unban</trigger>
|
|
||||||
</triggers>
|
|
||||||
</command>
|
|
||||||
|
|
||||||
<command name="unmute">
|
|
||||||
<classname>chat\system\command\UnmuteCommand</classname>
|
|
||||||
<triggers>
|
|
||||||
<trigger>unmute</trigger>
|
|
||||||
</triggers>
|
|
||||||
</command>
|
|
||||||
|
|
||||||
<command name="where">
|
|
||||||
<classname>chat\system\command\WhereCommand</classname>
|
|
||||||
<triggers>
|
|
||||||
<trigger>where</trigger>
|
|
||||||
</triggers>
|
|
||||||
</command>
|
|
||||||
|
|
||||||
<command name="whisper">
|
|
||||||
<classname>chat\system\command\WhisperCommand</classname>
|
|
||||||
<triggers>
|
|
||||||
<trigger>whisper</trigger>
|
|
||||||
</triggers>
|
|
||||||
</command>
|
|
||||||
</import>
|
|
||||||
</data>
|
|
@ -1,6 +0,0 @@
|
|||||||
<?php
|
|
||||||
define("CHAT_RELOADTIME", 3);
|
|
||||||
define("CHAT_AUTOAWAYTIME", 0);
|
|
||||||
define("CHAT_MAX_LENGTH", 500);
|
|
||||||
define("CHAT_ARCHIVE_AFTER", 90);
|
|
||||||
define("CHAT_LOG_ARCHIVETIME", 7);
|
|
138
contrib/build.php
Executable file
@ -0,0 +1,138 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
namespace be\bastelstu\chat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the Chat
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
*/
|
||||||
|
$packageXML = file_get_contents('package.xml');
|
||||||
|
preg_match('/<version>(.*?)<\/version>/', $packageXML, $matches);
|
||||||
|
echo "Building Tims Chat $matches[1]\n";
|
||||||
|
echo str_repeat("=", strlen("Building Tims Chat $matches[1]"))."\n";
|
||||||
|
|
||||||
|
echo <<<EOT
|
||||||
|
Cleaning up
|
||||||
|
-----------
|
||||||
|
|
||||||
|
EOT;
|
||||||
|
if (file_exists('package.xml.old')) {
|
||||||
|
file_put_contents('package.xml', file_get_contents('package.xml.old'));
|
||||||
|
unlink('package.xml.old');
|
||||||
|
}
|
||||||
|
if (file_exists('file.tar')) unlink('file.tar');
|
||||||
|
if (file_exists('template.tar')) unlink('template.tar');
|
||||||
|
if (file_exists('acptemplate.tar')) unlink('acptemplate.tar');
|
||||||
|
foreach (glob('file/acp/be.bastelstu.chat.nodePush/lib/*.js') as $nodeFile) unlink($nodeFile);
|
||||||
|
foreach (glob('file/js/*.js') as $jsFile) unlink($jsFile);
|
||||||
|
foreach (glob('file/acp/js/*.js') as $jsFile) unlink($jsFile);
|
||||||
|
if (file_exists('be.bastelstu.chat.tar')) unlink('be.bastelstu.chat.tar');
|
||||||
|
echo <<<EOT
|
||||||
|
|
||||||
|
Building JavaScript
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
EOT;
|
||||||
|
foreach (glob('file/js/*.{litcoffee,coffee}', GLOB_BRACE) as $coffeeFile) {
|
||||||
|
echo $coffeeFile."\n";
|
||||||
|
passthru('coffee -c '.escapeshellarg($coffeeFile), $code);
|
||||||
|
if ($code != 0) exit($code);
|
||||||
|
}
|
||||||
|
echo <<<EOT
|
||||||
|
|
||||||
|
Building ACP-JavaScript
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
EOT;
|
||||||
|
foreach (glob('file/acp/js/*.{litcoffee,coffee}', GLOB_BRACE) as $coffeeFile) {
|
||||||
|
echo $coffeeFile."\n";
|
||||||
|
passthru('coffee -c '.escapeshellarg($coffeeFile), $code);
|
||||||
|
if ($code != 0) exit($code);
|
||||||
|
}
|
||||||
|
echo <<<EOT
|
||||||
|
|
||||||
|
Compressing JavaScript
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
EOT;
|
||||||
|
foreach (glob('file/js/*.js', GLOB_BRACE) as $jsFile) {
|
||||||
|
echo $jsFile."\n";
|
||||||
|
passthru('uglifyjs '.escapeshellarg($jsFile).' --screw-ie8 -m -c --verbose --comments -d production=true -o '.escapeshellarg(substr($jsFile, 0, -3).'.min.js'), $code);
|
||||||
|
if ($code != 0) exit($code);
|
||||||
|
}
|
||||||
|
echo <<<EOT
|
||||||
|
|
||||||
|
Checking PHP for Syntax Errors
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
EOT;
|
||||||
|
chdir('file');
|
||||||
|
$check = null;
|
||||||
|
$check = function ($folder) use (&$check) {
|
||||||
|
if (is_file($folder)) {
|
||||||
|
if (substr($folder, -4) === '.php') {
|
||||||
|
passthru('php -l '.escapeshellarg($folder), $code);
|
||||||
|
if ($code != 0) exit($code);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$files = glob($folder.'/*');
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$check($file);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
$check('.');
|
||||||
|
echo <<<EOT
|
||||||
|
|
||||||
|
Building file.tar
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
EOT;
|
||||||
|
passthru('tar cvf ../file.tar --exclude=*coffee --exclude-vcs -- *', $code);
|
||||||
|
if ($code != 0) exit($code);
|
||||||
|
echo <<<EOT
|
||||||
|
|
||||||
|
Building template.tar
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
EOT;
|
||||||
|
chdir('../template');
|
||||||
|
passthru('tar cvf ../template.tar *', $code);
|
||||||
|
if ($code != 0) exit($code);
|
||||||
|
echo <<<EOT
|
||||||
|
|
||||||
|
Building acptemplate.tar
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
EOT;
|
||||||
|
chdir('../acptemplate');
|
||||||
|
passthru('tar cvf ../acptemplate.tar *', $code);
|
||||||
|
if ($code != 0) exit($code);
|
||||||
|
echo <<<EOT
|
||||||
|
|
||||||
|
Building be.bastelstu.chat.tar
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
EOT;
|
||||||
|
chdir('..');
|
||||||
|
file_put_contents('package.xml.old', file_get_contents('package.xml'));
|
||||||
|
file_put_contents('package.xml', preg_replace('~<date>\d{4}-\d{2}-\d{2}</date>~', '<date>'.date('Y-m-d').'</date>', file_get_contents('package.xml')));
|
||||||
|
file_put_contents('package.xml', str_replace('</version>', '</version><!-- git id '.trim(shell_exec('git describe --always')).' -->', file_get_contents('package.xml')));
|
||||||
|
passthru('tar cvf be.bastelstu.chat.tar --exclude=*.old --exclude=file --exclude-vcs --exclude=template --exclude=acptemplate --exclude=contrib -- *', $code);
|
||||||
|
if (file_exists('package.xml.old')) {
|
||||||
|
file_put_contents('package.xml', file_get_contents('package.xml.old'));
|
||||||
|
unlink('package.xml.old');
|
||||||
|
}
|
||||||
|
if ($code != 0) exit($code);
|
||||||
|
|
||||||
|
if (file_exists('file.tar')) unlink('file.tar');
|
||||||
|
if (file_exists('template.tar')) unlink('template.tar');
|
||||||
|
if (file_exists('acptemplate.tar')) unlink('acptemplate.tar');
|
||||||
|
foreach (glob('file/acp/be.bastelstu.chat.nodePush/lib/*.js') as $nodeFile) unlink($nodeFile);
|
||||||
|
foreach (glob('file/js/*.js') as $jsFile) unlink($jsFile);
|
||||||
|
foreach (glob('file/acp/js/*.js') as $jsFile) unlink($jsFile);
|
59
contrib/icon/chat.svg
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<!--
|
||||||
|
@author Maximilian Mader
|
||||||
|
@copyright 2011-2014 Tim Düsterhus
|
||||||
|
@license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
@package be.bastelstu.chat
|
||||||
|
-->
|
||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="16px" height="16px" viewBox="0 0 16 16" xml:space="preserve">
|
||||||
|
<title>Chat</title>
|
||||||
|
<desc>Chat Icon (outlined)</desc>
|
||||||
|
|
||||||
|
<defs>
|
||||||
|
<style type="text/css">
|
||||||
|
<![CDATA[
|
||||||
|
.Lower .bubble {
|
||||||
|
fill:none;
|
||||||
|
stroke:#ffffff;
|
||||||
|
stroke-opacity:1;
|
||||||
|
}
|
||||||
|
.Lower .leaderLine {
|
||||||
|
fill:#ffffff;
|
||||||
|
fill-opacity:1;
|
||||||
|
stroke:none;
|
||||||
|
}
|
||||||
|
.Upper .bubble {
|
||||||
|
fill:none;
|
||||||
|
stroke:#666666;
|
||||||
|
stroke-opacity:1;
|
||||||
|
}
|
||||||
|
.Upper .leaderLine {
|
||||||
|
fill:#666666;
|
||||||
|
fill-opacity:1;
|
||||||
|
stroke:none;
|
||||||
|
}
|
||||||
|
]]>
|
||||||
|
</style>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<g id="IconChat">
|
||||||
|
<g class="Lower" style="display:inline">
|
||||||
|
<path class="bubble"
|
||||||
|
d="M 15,8 A 6,5 0 1 1 3,8 6,5 0 1 1 15,8 z"
|
||||||
|
transform="matrix(1.0345788,0,0,0.95089627,-1.510083,0.10801843)" />
|
||||||
|
<path class="leaderLine"
|
||||||
|
d="m 3.9001344,11.947742 c 0.075049,1.120603 -0.7948094,1.693805 -1.4915533,2.143417 1.0104403,
|
||||||
|
0.104041 3.4597063,-0.953975 3.9167086,-1.276108 0.00808,-0.0057 -2.4251553,-0.867309 -2.4251553,-0.867309 z" />
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<g class="Upper" style="display:inline">
|
||||||
|
<path class="bubble"
|
||||||
|
d="M 15,8 A 6,5 0 1 1 3,8 6,5 0 1 1 15,8 z"
|
||||||
|
transform="matrix(1.0345788,0,0,0.95089627,-1.5100816,-0.50773368)" />
|
||||||
|
<path class="leaderLine"
|
||||||
|
d="m 3.9001358,11.331991 c 0.075049,1.120603 -0.7948094,1.693805 -1.4915533,2.143417 1.0104403,
|
||||||
|
0.104041 3.4597063,-0.953975 3.9167086,-1.276108 0.00808,-0.0057 -2.4251553,-0.867309 -2.4251553,-0.867309 z" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
BIN
contrib/icon/chat16.png
Normal file
After Width: | Height: | Size: 657 B |
BIN
contrib/icon/chat32.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
contrib/icon/chat48.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
contrib/icon/chatL.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
contrib/icon/chatM.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
contrib/icon/chatS.png
Normal file
After Width: | Height: | Size: 795 B |
9
dashboardBox.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/dashboardBox.xsd">
|
||||||
|
<import>
|
||||||
|
<dashboardbox name="be.bastelstu.chat.onlineList">
|
||||||
|
<classname><![CDATA[chat\system\dashboard\box\OnlineListDashboardBox]]></classname>
|
||||||
|
<boxtype>content</boxtype>
|
||||||
|
</dashboardbox>
|
||||||
|
</import>
|
||||||
|
</data>
|
@ -1,166 +1,17 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/maelstrom/eventListener.xsd">
|
<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/maelstrom/eventListener.xsd">
|
||||||
<import>
|
<import>
|
||||||
<!-- Hourly Cleanup -->
|
<eventlistener>
|
||||||
<eventlistener name="hourlyCleanUpUser">
|
|
||||||
<eventclassname>wcf\system\cronjob\HourlyCleanUpCronjob</eventclassname>
|
<eventclassname>wcf\system\cronjob\HourlyCleanUpCronjob</eventclassname>
|
||||||
<eventname>execute</eventname>
|
<eventname>execute</eventname>
|
||||||
<listenerclassname>chat\system\event\listener\HourlyCleanUpCronjobExecuteChatCleanUpListener</listenerclassname>
|
<listenerclassname>chat\system\event\listener\HourlyCleanUpCronjobExecuteChatCleanUpListener</listenerclassname>
|
||||||
<environment>user</environment>
|
<environment>user</environment>
|
||||||
</eventlistener>
|
</eventlistener>
|
||||||
<eventlistener name="hourlyCleanUpAdmin">
|
<eventlistener>
|
||||||
<eventclassname>wcf\system\cronjob\HourlyCleanUpCronjob</eventclassname>
|
<eventclassname>wcf\system\cronjob\HourlyCleanUpCronjob</eventclassname>
|
||||||
<eventname>execute</eventname>
|
<eventname>execute</eventname>
|
||||||
<listenerclassname>chat\system\event\listener\HourlyCleanUpCronjobExecuteChatCleanUpListener</listenerclassname>
|
<listenerclassname>chat\system\event\listener\HourlyCleanUpCronjobExecuteChatCleanUpListener</listenerclassname>
|
||||||
<environment>admin</environment>
|
<environment>admin</environment>
|
||||||
</eventlistener>
|
</eventlistener>
|
||||||
|
|
||||||
<!-- Temprooms -->
|
|
||||||
<eventlistener name="temproomHourlyCleanUpUser">
|
|
||||||
<eventclassname>wcf\system\cronjob\HourlyCleanUpCronjob</eventclassname>
|
|
||||||
<eventname>execute</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\HourlyCleanUpCronjobExecuteTemproomListener</listenerclassname>
|
|
||||||
<environment>user</environment>
|
|
||||||
</eventlistener>
|
|
||||||
<eventlistener name="temproomHourlyCleanUpAdmin">
|
|
||||||
<eventclassname>wcf\system\cronjob\HourlyCleanUpCronjob</eventclassname>
|
|
||||||
<eventname>execute</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\HourlyCleanUpCronjobExecuteTemproomListener</listenerclassname>
|
|
||||||
<environment>admin</environment>
|
|
||||||
</eventlistener>
|
|
||||||
<eventlistener name="temproomCanSee">
|
|
||||||
<eventclassname>chat\data\room\Room</eventclassname>
|
|
||||||
<eventname>canSee</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\RoomCanSeeTemproomListener</listenerclassname>
|
|
||||||
<environment>user</environment>
|
|
||||||
</eventlistener>
|
|
||||||
<eventlistener name="temproomRoomList">
|
|
||||||
<eventclassname>chat\acp\page\RoomListPage</eventclassname>
|
|
||||||
<eventname>calculateNumberOfPages</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\RoomListPageTemproomListener</listenerclassname>
|
|
||||||
<environment>admin</environment>
|
|
||||||
</eventlistener>
|
|
||||||
<eventlistener name="temproomRoomEdit">
|
|
||||||
<eventclassname>chat\acp\form\RoomEditForm</eventclassname>
|
|
||||||
<eventname>readParameters</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\RoomEditFormTemproomListener</listenerclassname>
|
|
||||||
<environment>admin</environment>
|
|
||||||
</eventlistener>
|
|
||||||
<eventlistener name="temproomSuspensionList">
|
|
||||||
<eventclassname>chat\acp\page\SuspensionListPage</eventclassname>
|
|
||||||
<eventname>readData</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\SuspensionListPageTemproomListener</listenerclassname>
|
|
||||||
<environment>admin</environment>
|
|
||||||
</eventlistener>
|
|
||||||
|
|
||||||
<!-- User Limit -->
|
|
||||||
<eventlistener name="userLimitCanJoin">
|
|
||||||
<eventclassname>chat\data\room\Room</eventclassname>
|
|
||||||
<eventname>canJoin</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\RoomCanJoinUserLimitListener</listenerclassname>
|
|
||||||
<environment>user</environment>
|
|
||||||
</eventlistener>
|
|
||||||
|
|
||||||
<!-- Suspensions -->
|
|
||||||
<eventlistener name="suspensionCanJoin">
|
|
||||||
<eventclassname>chat\data\room\Room</eventclassname>
|
|
||||||
<eventname>canJoin</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\RoomCanJoinBanListener</listenerclassname>
|
|
||||||
<environment>user</environment>
|
|
||||||
</eventlistener>
|
|
||||||
<eventlistener name="suspensionCanWritePublicly">
|
|
||||||
<eventclassname>chat\data\room\Room</eventclassname>
|
|
||||||
<eventname>canWritePublicly</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\RoomCanWritePubliclyMuteListener</listenerclassname>
|
|
||||||
<environment>user</environment>
|
|
||||||
</eventlistener>
|
|
||||||
<eventlistener name="suspensionInfoCommand">
|
|
||||||
<eventclassname>chat\system\command\InfoCommand</eventclassname>
|
|
||||||
<eventname>execute</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\InfoCommandSuspensionsListener</listenerclassname>
|
|
||||||
<environment>user</environment>
|
|
||||||
</eventlistener>
|
|
||||||
<eventlistener name="moderatorPermissions">
|
|
||||||
<eventclassname>chat\data\room\RoomAction</eventclassname>
|
|
||||||
<eventname>getUsers</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\RoomActionGetUsersModeratorListener</listenerclassname>
|
|
||||||
<environment>user</environment>
|
|
||||||
</eventlistener>
|
|
||||||
</import>
|
</import>
|
||||||
|
|
||||||
<delete>
|
|
||||||
<!-- Hourly Cleanup -->
|
|
||||||
<eventlistener>
|
|
||||||
<eventclassname>wcf\system\cronjob\HourlyCleanUpCronjob</eventclassname>
|
|
||||||
<eventname>execute</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\HourlyCleanUpCronjobExecuteChatCleanUpListener</listenerclassname>
|
|
||||||
<environment>user</environment>
|
|
||||||
</eventlistener>
|
|
||||||
<eventlistener>
|
|
||||||
<eventclassname>wcf\system\cronjob\HourlyCleanUpCronjob</eventclassname>
|
|
||||||
<eventname>execute</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\HourlyCleanUpCronjobExecuteChatCleanUpListener</listenerclassname>
|
|
||||||
<environment>admin</environment>
|
|
||||||
</eventlistener>
|
|
||||||
|
|
||||||
<!-- Temprooms -->
|
|
||||||
<eventlistener>
|
|
||||||
<eventclassname>wcf\system\cronjob\HourlyCleanUpCronjob</eventclassname>
|
|
||||||
<eventname>execute</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\HourlyCleanUpCronjobExecuteTemproomListener</listenerclassname>
|
|
||||||
<environment>user</environment>
|
|
||||||
</eventlistener>
|
|
||||||
<eventlistener>
|
|
||||||
<eventclassname>wcf\system\cronjob\HourlyCleanUpCronjob</eventclassname>
|
|
||||||
<eventname>execute</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\HourlyCleanUpCronjobExecuteTemproomListener</listenerclassname>
|
|
||||||
<environment>admin</environment>
|
|
||||||
</eventlistener>
|
|
||||||
<eventlistener>
|
|
||||||
<eventclassname>chat\data\room\Room</eventclassname>
|
|
||||||
<eventname>canSee</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\RoomCanSeeTemproomListener</listenerclassname>
|
|
||||||
<environment>user</environment>
|
|
||||||
</eventlistener>
|
|
||||||
<eventlistener>
|
|
||||||
<eventclassname>chat\acp\page\RoomListPage</eventclassname>
|
|
||||||
<eventname>calculateNumberOfPages</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\RoomListPageTemproomListener</listenerclassname>
|
|
||||||
<environment>admin</environment>
|
|
||||||
</eventlistener>
|
|
||||||
<eventlistener>
|
|
||||||
<eventclassname>chat\acp\form\RoomEditForm</eventclassname>
|
|
||||||
<eventname>readParameters</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\RoomEditFormTemproomListener</listenerclassname>
|
|
||||||
<environment>admin</environment>
|
|
||||||
</eventlistener>
|
|
||||||
|
|
||||||
<!-- User Limit -->
|
|
||||||
<eventlistener>
|
|
||||||
<eventclassname>chat\data\room\Room</eventclassname>
|
|
||||||
<eventname>canJoin</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\RoomCanJoinUserLimitListener</listenerclassname>
|
|
||||||
<environment>user</environment>
|
|
||||||
</eventlistener>
|
|
||||||
|
|
||||||
<!-- Suspensions -->
|
|
||||||
<eventlistener>
|
|
||||||
<eventclassname>chat\data\room\Room</eventclassname>
|
|
||||||
<eventname>canJoin</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\RoomCanJoinBanListener</listenerclassname>
|
|
||||||
<environment>user</environment>
|
|
||||||
</eventlistener>
|
|
||||||
<eventlistener>
|
|
||||||
<eventclassname>chat\data\room\Room</eventclassname>
|
|
||||||
<eventname>canWritePublicly</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\RoomCanWritePubliclyMuteListener</listenerclassname>
|
|
||||||
<environment>user</environment>
|
|
||||||
</eventlistener>
|
|
||||||
<eventlistener>
|
|
||||||
<eventclassname>chat\system\command\InfoCommand</eventclassname>
|
|
||||||
<eventname>execute</eventname>
|
|
||||||
<listenerclassname>chat\system\event\listener\InfoCommandSuspensionsListener</listenerclassname>
|
|
||||||
<environment>user</environment>
|
|
||||||
</eventlistener>
|
|
||||||
</delete>
|
|
||||||
</data>
|
</data>
|
61
file/acp/be.bastelstu.chat.install.php
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
namespace be\bastelstu\chat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles installation of Tims Chat.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
*/
|
||||||
|
// @codingStandardsIgnoreFile
|
||||||
|
final class Install {
|
||||||
|
/**
|
||||||
|
* Contains all the styles the current installation has.
|
||||||
|
*
|
||||||
|
* @var array<\wcf\data\style\Style>
|
||||||
|
*/
|
||||||
|
private $styles = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do we need to update the page title?
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
private $updateTitle = false;
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
$this->styles = \wcf\system\style\StyleHandler::getInstance()->getAvailableStyles();
|
||||||
|
if (!defined('PAGE_TITLE') || !PAGE_TITLE) $this->updateTitle = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets styles.
|
||||||
|
*/
|
||||||
|
public function execute() {
|
||||||
|
foreach ($this->styles as $style) {
|
||||||
|
\wcf\system\style\StyleHandler::getInstance()->resetStylesheet($style);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->updateTitle) {
|
||||||
|
$sql = "UPDATE
|
||||||
|
wcf".WCF_N."_option
|
||||||
|
SET
|
||||||
|
optionValue = ?
|
||||||
|
WHERE
|
||||||
|
optionName = ?";
|
||||||
|
$stmt = \wcf\system\WCF::getDB()->prepareStatement($sql);
|
||||||
|
$stmt->execute(array('Tims Chat 3', 'page_title'));
|
||||||
|
\wcf\data\option\OptionEditor::resetCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
\wcf\system\dashboard\DashboardHandler::setDefaultValues('com.woltlab.wcf.user.DashboardPage', array(
|
||||||
|
// content
|
||||||
|
'be.bastelstu.chat.onlineList' => 1
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$install = new Install();
|
||||||
|
$install->execute();
|
57
file/acp/be.bastelstu.chat.update.php
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
namespace be\bastelstu\chat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles updates of Tims Chat.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
*/
|
||||||
|
// @codingStandardsIgnoreFile
|
||||||
|
final class Update {
|
||||||
|
/**
|
||||||
|
* Contains all the rooms the current installation has.
|
||||||
|
*
|
||||||
|
* @var array<\wcf\data\chat\room\ChatRoom>
|
||||||
|
*/
|
||||||
|
private $rooms = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains all the styles the current installation has.
|
||||||
|
*
|
||||||
|
* @var array<\wcf\data\style\Style>
|
||||||
|
*/
|
||||||
|
private $styles = null;
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
$this->rooms = \chat\data\room\RoomCache::getInstance()->getRooms();
|
||||||
|
$this->styles = \wcf\system\style\StyleHandler::getInstance()->getAvailableStyles();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies users to refresh the chat as the JS may no longer be fully compatible with the PHP code.
|
||||||
|
* Resets styles.
|
||||||
|
*/
|
||||||
|
public function execute() {
|
||||||
|
foreach ($this->rooms as $room) {
|
||||||
|
$messageAction = new \chat\data\message\MessageAction(array(), 'create', array(
|
||||||
|
'data' => array(
|
||||||
|
'roomID' => $room->roomID,
|
||||||
|
'time' => TIME_NOW,
|
||||||
|
'type' => \chat\data\message\Message::TYPE_INFORMATION,
|
||||||
|
'message' => \wcf\system\WCF::getLanguage()->get('chat.global.information.chatUpdate')
|
||||||
|
)
|
||||||
|
));
|
||||||
|
$messageAction->executeAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->styles as $style) {
|
||||||
|
\wcf\system\style\StyleHandler::getInstance()->resetStylesheet($style);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$update = new Update();
|
||||||
|
$update->execute();
|
15
file/acp/global.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
*/
|
||||||
|
// define paths
|
||||||
|
define('RELATIVE_CHAT_DIR', '../');
|
||||||
|
|
||||||
|
// include config
|
||||||
|
require_once(dirname(dirname(__FILE__)).'/config.inc.php');
|
||||||
|
|
||||||
|
// include WCF
|
||||||
|
require_once(RELATIVE_WCF_DIR.'acp/global.php');
|
9
file/acp/index.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
*/
|
||||||
|
require_once(__DIR__.'/global.php');
|
||||||
|
wcf\system\request\RequestHandler::getInstance()->handle('chat', true);
|
92
file/acp/js/be.bastelstu.Chat.ACP.Log.litcoffee
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
Tims Chat 3
|
||||||
|
===========
|
||||||
|
|
||||||
|
This is the javascript file providing functions related to the message log for [##Tims Chat##](https://github.com/wbbaddons/Tims-Chat).
|
||||||
|
|
||||||
|
### Copyright Information
|
||||||
|
# @author Maximilian Mader
|
||||||
|
# @copyright 2010-2014 Tim Düsterhus
|
||||||
|
# @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
# @package be.bastelstu.chat
|
||||||
|
###
|
||||||
|
|
||||||
|
## Code
|
||||||
|
|
||||||
|
(($, window) ->
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
_messageLogContent = null
|
||||||
|
_hasContent = {}
|
||||||
|
_proxy = null
|
||||||
|
|
||||||
|
init = ->
|
||||||
|
_messageLogContent = $ '#messageLogContent'
|
||||||
|
|
||||||
|
activeMenuItem = _messageLogContent.data 'active'
|
||||||
|
enableProxy = false
|
||||||
|
|
||||||
|
_messageLogContent.find('div.tabMenuContent > .subTabMenuContent').each (index, container) ->
|
||||||
|
containerID = $(container).wcfIdentify()
|
||||||
|
|
||||||
|
unless $("##{containerID}").hasClass 'empty'
|
||||||
|
_hasContent[containerID] = true
|
||||||
|
else
|
||||||
|
_hasContent[containerID] = false
|
||||||
|
enableProxy = true
|
||||||
|
|
||||||
|
if enableProxy
|
||||||
|
_proxy = new WCF.Action.Proxy
|
||||||
|
success: _success
|
||||||
|
|
||||||
|
_messageLogContent.bind 'wcftabsbeforeactivate',
|
||||||
|
_loadContent
|
||||||
|
|
||||||
|
if not _hasContent[activeMenuItem]
|
||||||
|
_loadContent {},
|
||||||
|
newPanel: $("##{activeMenuItem}")
|
||||||
|
newTab: $("##{activeMenuItem}").parent().find(".menu > ul > li").first()
|
||||||
|
|
||||||
|
_loadContent = (event, ui) ->
|
||||||
|
containerID = $(ui.newPanel).attr 'id'
|
||||||
|
|
||||||
|
if $("##{$(ui.newPanel).attr('id')}").hasClass 'tabMenuContainer'
|
||||||
|
containerID = $("##{containerID} > .subTabMenuContent").first().attr 'id'
|
||||||
|
tab = $("##{containerID}").parent().find(".menu > ul > li").first()
|
||||||
|
else
|
||||||
|
tab = $ ui.newTab
|
||||||
|
|
||||||
|
unless _hasContent[containerID]
|
||||||
|
start = _messageLogContent.data('baseTime') + (tab.data('hour') * 3600) + (tab.data('minutes') * 60)
|
||||||
|
|
||||||
|
_proxy.setOption 'data',
|
||||||
|
actionName: 'getMessages'
|
||||||
|
className: 'chat\\data\\message\\MessageAction'
|
||||||
|
parameters:
|
||||||
|
containerID: containerID
|
||||||
|
start: start
|
||||||
|
end: start + 1799
|
||||||
|
roomID: _messageLogContent.data 'roomID'
|
||||||
|
do _proxy.sendRequest
|
||||||
|
|
||||||
|
_success = (data, textStatus, jqWHR) ->
|
||||||
|
containerID = data.returnValues.containerID
|
||||||
|
_hasContent[containerID] = true
|
||||||
|
|
||||||
|
content = _messageLogContent.find "##{containerID}"
|
||||||
|
unless data.returnValues.template is ''
|
||||||
|
$("<div>#{data.returnValues.template}</div>").hide().appendTo content
|
||||||
|
unless data.returnValues.noMessages
|
||||||
|
content.addClass 'tabularBox'
|
||||||
|
|
||||||
|
do content.children().first().show
|
||||||
|
Log =
|
||||||
|
TabMenu:
|
||||||
|
init: init
|
||||||
|
|
||||||
|
window.be ?= {}
|
||||||
|
be.bastelstu ?= {}
|
||||||
|
be.bastelstu.Chat ?= {}
|
||||||
|
be.bastelstu.Chat.ACP ?= {}
|
||||||
|
be.bastelstu.Chat.ACP.Log ?= {}
|
||||||
|
window.be.bastelstu.Chat.ACP.Log = Log
|
||||||
|
)(jQuery, @)
|
13
file/global.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
*/
|
||||||
|
|
||||||
|
// include config
|
||||||
|
require_once(__DIR__.'/config.inc.php');
|
||||||
|
|
||||||
|
// include wcf
|
||||||
|
require_once(RELATIVE_WCF_DIR.'global.php');
|
BIN
file/images/chatLogo.png
Normal file
After Width: | Height: | Size: 6.1 KiB |
10
file/index.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once(__DIR__.'/global.php');
|
||||||
|
\wcf\system\request\RequestHandler::getInstance()->handle('chat');
|
1305
file/js/be.bastelstu.Chat.litcoffee
Normal file
150
file/lib/acp/form/RoomAddForm.class.php
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\acp\form;
|
||||||
|
use \wcf\system\exception\UserInputException;
|
||||||
|
use \wcf\system\language\I18nHandler;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the chatroom add form.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage acp.form
|
||||||
|
*/
|
||||||
|
class RoomAddForm extends \wcf\form\AbstractForm {
|
||||||
|
/**
|
||||||
|
* @see \wcf\acp\page\AbstractPage::$activeMenuItem
|
||||||
|
*/
|
||||||
|
public $activeMenuItem = 'chat.acp.menu.link.room.add';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::$neededPermissions
|
||||||
|
*/
|
||||||
|
public $neededPermissions = array('admin.chat.canAddRoom');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Title of the room
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $title = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Topic of the room
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $topic = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::__construct()
|
||||||
|
*/
|
||||||
|
public function __run() {
|
||||||
|
$this->objectTypeID = \wcf\system\acl\ACLHandler::getInstance()->getObjectTypeID('be.bastelstu.chat.room');
|
||||||
|
|
||||||
|
parent::__run();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\IPage::readParameters()
|
||||||
|
*/
|
||||||
|
public function readParameters() {
|
||||||
|
parent::readParameters();
|
||||||
|
|
||||||
|
I18nHandler::getInstance()->register('title');
|
||||||
|
I18nHandler::getInstance()->register('topic');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\form\IForm::readFormParameters()
|
||||||
|
*/
|
||||||
|
public function readFormParameters() {
|
||||||
|
parent::readFormParameters();
|
||||||
|
|
||||||
|
I18nHandler::getInstance()->readValues();
|
||||||
|
|
||||||
|
if (I18nHandler::getInstance()->isPlainValue('title')) $this->title = I18nHandler::getInstance()->getValue('title');
|
||||||
|
if (I18nHandler::getInstance()->isPlainValue('topic')) $this->topic = I18nHandler::getInstance()->getValue('topic');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\form\IForm::validate()
|
||||||
|
*/
|
||||||
|
public function validate() {
|
||||||
|
parent::validate();
|
||||||
|
|
||||||
|
// validate title
|
||||||
|
if (!I18nHandler::getInstance()->validateValue('title')) {
|
||||||
|
throw new UserInputException('title');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\form\IForm::save()
|
||||||
|
*/
|
||||||
|
public function save() {
|
||||||
|
parent::save();
|
||||||
|
|
||||||
|
// save room
|
||||||
|
$this->objectAction = new \chat\data\room\RoomAction(array(), 'create', array('data' => array_merge($this->additionalFields, array(
|
||||||
|
'title' => $this->title,
|
||||||
|
'topic' => $this->topic
|
||||||
|
))));
|
||||||
|
$this->objectAction->executeAction();
|
||||||
|
$returnValues = $this->objectAction->getReturnValues();
|
||||||
|
$roomEditor = new \chat\data\room\RoomEditor($returnValues['returnValues']);
|
||||||
|
$roomID = $returnValues['returnValues']->roomID;
|
||||||
|
|
||||||
|
if (!I18nHandler::getInstance()->isPlainValue('title')) {
|
||||||
|
I18nHandler::getInstance()->save('title', 'chat.room.title'.$roomID, 'chat.room', \chat\util\ChatUtil::getPackageID());
|
||||||
|
|
||||||
|
// update title
|
||||||
|
$roomEditor->update(array(
|
||||||
|
'title' => 'chat.room.title'.$roomID
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!I18nHandler::getInstance()->isPlainValue('topic')) {
|
||||||
|
I18nHandler::getInstance()->save('topic', 'chat.room.topic'.$roomID, 'chat.room', \chat\util\ChatUtil::getPackageID());
|
||||||
|
|
||||||
|
// update topic
|
||||||
|
$roomEditor->update(array(
|
||||||
|
'topic' => 'chat.room.topic'.$roomID
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
\wcf\system\acl\ACLHandler::getInstance()->save($roomID, $this->objectTypeID);
|
||||||
|
\wcf\system\acl\ACLHandler::getInstance()->disableAssignVariables();
|
||||||
|
\chat\system\permission\PermissionHandler::clearCache();
|
||||||
|
|
||||||
|
$this->saved();
|
||||||
|
|
||||||
|
// reset values
|
||||||
|
$this->topic = $this->title = '';
|
||||||
|
I18nHandler::getInstance()->reset();
|
||||||
|
|
||||||
|
// show success
|
||||||
|
WCF::getTPL()->assign(array(
|
||||||
|
'success' => true
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\IPage::assignVariables()
|
||||||
|
*/
|
||||||
|
public function assignVariables() {
|
||||||
|
parent::assignVariables();
|
||||||
|
|
||||||
|
I18nHandler::getInstance()->assignVariables();
|
||||||
|
\wcf\system\acl\ACLHandler::getInstance()->assignVariables($this->objectTypeID);
|
||||||
|
|
||||||
|
WCF::getTPL()->assign(array(
|
||||||
|
'action' => 'add',
|
||||||
|
'title' => $this->title,
|
||||||
|
'topic' => $this->topic,
|
||||||
|
'objectTypeID' => $this->objectTypeID
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
132
file/lib/acp/form/RoomEditForm.class.php
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\acp\form;
|
||||||
|
use \wcf\system\language\I18nHandler;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the chatroom edit form.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage acp.form
|
||||||
|
*/
|
||||||
|
class RoomEditForm extends RoomAddForm {
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::$templateName
|
||||||
|
*/
|
||||||
|
public $templateName = 'roomAdd';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\acp\form\ACPForm::$activeMenuItem
|
||||||
|
*/
|
||||||
|
public $activeMenuItem = 'chat.acp.menu.link.chat';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::$neededPermissions
|
||||||
|
*/
|
||||||
|
public $neededPermissions = array('admin.chat.canEditRoom');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* room id
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public $roomID = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* room object
|
||||||
|
*
|
||||||
|
* @var \chat\data\room\Room
|
||||||
|
*/
|
||||||
|
public $roomObj = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\IPage::readParameters()
|
||||||
|
*/
|
||||||
|
public function readParameters() {
|
||||||
|
parent::readParameters();
|
||||||
|
|
||||||
|
if (isset($_REQUEST['id'])) $this->roomID = intval($_REQUEST['id']);
|
||||||
|
$this->roomObj = new \chat\data\room\Room($this->roomID);
|
||||||
|
if (!$this->roomObj->roomID) {
|
||||||
|
throw new \wcf\system\exception\IllegalLinkException();
|
||||||
|
}
|
||||||
|
if (!$this->roomObj->permanent) {
|
||||||
|
throw new \wcf\system\exception\PermissionDeniedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\form\IForm::save()
|
||||||
|
*/
|
||||||
|
public function save() {
|
||||||
|
\wcf\form\AbstractForm::save();
|
||||||
|
|
||||||
|
$this->title = 'chat.room.title'.$this->roomObj->roomID;
|
||||||
|
if (I18nHandler::getInstance()->isPlainValue('title')) {
|
||||||
|
I18nHandler::getInstance()->remove($this->title);
|
||||||
|
$this->title = I18nHandler::getInstance()->getValue('title');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
I18nHandler::getInstance()->save('title', $this->title, 'chat.room', \chat\util\ChatUtil::getPackageID());
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->topic = 'chat.room.topic'.$this->roomObj->roomID;
|
||||||
|
if (I18nHandler::getInstance()->isPlainValue('topic')) {
|
||||||
|
I18nHandler::getInstance()->remove($this->topic);
|
||||||
|
$this->topic = I18nHandler::getInstance()->getValue('topic');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
I18nHandler::getInstance()->save('topic', $this->topic, 'chat.room', \chat\util\ChatUtil::getPackageID());
|
||||||
|
}
|
||||||
|
|
||||||
|
\wcf\system\acl\ACLHandler::getInstance()->save($this->roomID, $this->objectTypeID);
|
||||||
|
\wcf\system\acl\ACLHandler::getInstance()->disableAssignVariables();
|
||||||
|
\chat\system\permission\PermissionHandler::clearCache();
|
||||||
|
|
||||||
|
// update room
|
||||||
|
$this->objectAction = new \chat\data\room\RoomAction(array($this->roomID), 'update', array('data' => array_merge($this->additionalFields, array(
|
||||||
|
'title' => $this->title,
|
||||||
|
'topic' => $this->topic
|
||||||
|
))));
|
||||||
|
$this->objectAction->executeAction();
|
||||||
|
|
||||||
|
$this->saved();
|
||||||
|
|
||||||
|
// show success
|
||||||
|
WCF::getTPL()->assign(array(
|
||||||
|
'success' => true
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\IPage::readData()
|
||||||
|
*/
|
||||||
|
public function readData() {
|
||||||
|
parent::readData();
|
||||||
|
|
||||||
|
if (!count($_POST)) {
|
||||||
|
I18nHandler::getInstance()->setOptions('title', \chat\util\ChatUtil::getPackageID(), $this->roomObj->title, 'chat.room.title\d+');
|
||||||
|
I18nHandler::getInstance()->setOptions('topic', \chat\util\ChatUtil::getPackageID(), $this->roomObj->topic, 'chat.room.topic\d+');
|
||||||
|
|
||||||
|
$this->title = $this->roomObj->title;
|
||||||
|
$this->topic = $this->roomObj->topic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\IPage::assignVariables()
|
||||||
|
*/
|
||||||
|
public function assignVariables() {
|
||||||
|
parent::assignVariables();
|
||||||
|
|
||||||
|
I18nHandler::getInstance()->assignVariables((bool) count($_POST));
|
||||||
|
|
||||||
|
WCF::getTPL()->assign(array(
|
||||||
|
'roomID' => $this->roomID,
|
||||||
|
'action' => 'edit'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
183
file/lib/acp/page/ChatSuspensionListPage.class.php
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\acp\page;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists chat suspensions.
|
||||||
|
*
|
||||||
|
* @author Maximilian Mader
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage acp.page
|
||||||
|
*/
|
||||||
|
class ChatSuspensionListPage extends \wcf\page\SortablePage {
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::$activeMenuItem
|
||||||
|
*/
|
||||||
|
public $activeMenuItem = 'chat.acp.menu.link.suspension.list';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::$neededPermissions
|
||||||
|
*/
|
||||||
|
public $neededPermissions = array('admin.chat.canManageSuspensions');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\SortablePage::$defaultSortField
|
||||||
|
*/
|
||||||
|
public $defaultSortField = 'expires';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\SortablePage::$validSortFields
|
||||||
|
*/
|
||||||
|
public $validSortFields = array('suspensionID', 'userID', 'username', 'roomID', 'type', 'expires', 'issuer', 'time', 'reason');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\MultipleLinkPage::$objectListClassName
|
||||||
|
*/
|
||||||
|
public $objectListClassName = 'chat\data\suspension\SuspensionList';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* type filter
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public $filterSuspensionType = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* user filter
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public $filterUserID = null;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* username
|
||||||
|
*
|
||||||
|
* @var String
|
||||||
|
*/
|
||||||
|
public $filterUsername = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* issuer filter
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public $filterIssuerUserID = null;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* issuer username
|
||||||
|
*
|
||||||
|
* @var String
|
||||||
|
*/
|
||||||
|
public $filterIssuerUsername = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* room filter
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public $filterRoomID = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* display revoked suspensions
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public $displayRevoked = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\IPage::readParameters()
|
||||||
|
*/
|
||||||
|
public function readParameters() {
|
||||||
|
parent::readParameters();
|
||||||
|
|
||||||
|
// get usernames
|
||||||
|
if (isset($_REQUEST['username']) && !empty($_REQUEST['username'])) $this->filterUsername = \wcf\util\StringUtil::trim($_REQUEST['username']);
|
||||||
|
if (isset($_REQUEST['issuerUsername']) && !empty($_REQUEST['issuerUsername'])) $this->filterIssuerUsername = \wcf\util\StringUtil::trim($_REQUEST['issuerUsername']);
|
||||||
|
|
||||||
|
// get user IDs by username
|
||||||
|
if ($this->filterUsername != null) $this->filterUserID = \wcf\data\user\UserProfile::getUserProfileByUsername($this->filterUsername)->userID;
|
||||||
|
if ($this->filterIssuerUsername != null) $this->filterIssuerUserID = \wcf\data\user\UserProfile::getUserProfileByUsername($this->filterIssuerUsername)->userID;
|
||||||
|
|
||||||
|
// get user IDs by request if no username was sent
|
||||||
|
if ($this->filterUserID === null && isset($_REQUEST['userID']) && !empty($_REQUEST['userID'])) $this->filterUserID = intval($_REQUEST['userID']);
|
||||||
|
if ($this->filterIssuerUserID === null && isset($_REQUEST['issuerUserID']) && !empty($_REQUEST['issuerUserID'])) $this->filterIssuerUserID = intval($_REQUEST['issuerUserID']);
|
||||||
|
|
||||||
|
// get usernames by ID if no usernames were sent
|
||||||
|
if ($this->filterUsername === null) $this->filterUsername = \wcf\data\user\UserProfile::getUserProfile($this->filterUserID);
|
||||||
|
if ($this->filterIssuerUsername === null) $this->filterIssuerUsername = \wcf\data\user\UserProfile::getUserProfile($this->filterIssuerUserID);
|
||||||
|
|
||||||
|
// get room IDs by request
|
||||||
|
if (isset($_REQUEST['roomID']) && $_REQUEST['roomID'] != -1) {
|
||||||
|
$this->filterRoomID = intval($_REQUEST['roomID']);
|
||||||
|
$room = \chat\data\room\RoomCache::getInstance()->getRoom($this->filterRoomID);
|
||||||
|
if (!$room) throw new \wcf\system\exception\IllegalLinkException();
|
||||||
|
if (!$room->permanent) throw new \wcf\system\exception\PermissionDeniedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($_REQUEST['suspensionType']) && !empty($_REQUEST['suspensionType'])) $this->filterSuspensionType = \wcf\util\StringUtil::trim($_REQUEST['suspensionType']);
|
||||||
|
|
||||||
|
// display revoked
|
||||||
|
if (isset($_REQUEST['displayRevoked'])) $this->displayRevoked = intval($_REQUEST['displayRevoked']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see wcf\page\IPage::assignVariables()
|
||||||
|
*/
|
||||||
|
public function assignVariables() {
|
||||||
|
parent::assignVariables();
|
||||||
|
|
||||||
|
$rooms = \chat\data\room\RoomCache::getInstance()->getRooms();
|
||||||
|
foreach ($rooms as $id => $room) {
|
||||||
|
if (!$room->permanent) unset($rooms[$id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
WCF::getTPL()->assign(array(
|
||||||
|
'availableRooms' => $rooms,
|
||||||
|
'roomID' => ($this->filterRoomID !== null) ? $this->filterRoomID : -1,
|
||||||
|
'username' => $this->filterUsername,
|
||||||
|
'issuerUsername' => $this->filterIssuerUsername,
|
||||||
|
'suspensionType' => $this->filterSuspensionType,
|
||||||
|
'userID' => $this->filterUserID,
|
||||||
|
'issuerUserID' => $this->filterIssuerUserID,
|
||||||
|
'displayRevoked' => $this->displayRevoked
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\MultipleLinkPage::readObjects()
|
||||||
|
*/
|
||||||
|
protected function initObjectList() {
|
||||||
|
parent::initObjectList();
|
||||||
|
|
||||||
|
$this->objectList->sqlSelects .= "user_table_muted.username, user_table_issuer.username AS issuerUsername, user_table_revoker.username AS revokerUsername, room_table.title AS roomTitle";
|
||||||
|
$this->objectList->sqlJoins .= "
|
||||||
|
LEFT JOIN wcf".WCF_N."_user user_table_muted
|
||||||
|
ON suspension.userID = user_table_muted.userID
|
||||||
|
LEFT JOIN wcf".WCF_N."_user user_table_issuer
|
||||||
|
ON suspension.issuer = user_table_issuer.userID
|
||||||
|
LEFT JOIN wcf".WCF_N."_user user_table_revoker
|
||||||
|
ON suspension.revoker = user_table_revoker.userID";
|
||||||
|
$conditionJoins = " LEFT JOIN chat".WCF_N."_room room_table
|
||||||
|
ON suspension.roomID = room_table.roomID";
|
||||||
|
$this->objectList->sqlConditionJoins .= $conditionJoins;
|
||||||
|
$this->objectList->sqlJoins .= $conditionJoins;
|
||||||
|
|
||||||
|
if (!$this->displayRevoked) {
|
||||||
|
$this->objectList->getConditionBuilder()->add('expires > ?', array(TIME_NOW));
|
||||||
|
}
|
||||||
|
$this->objectList->getConditionBuilder()->add('(room_table.permanent = ? OR suspension.roomID IS NULL)', array(1));
|
||||||
|
if ($this->filterSuspensionType !== null) $this->objectList->getConditionBuilder()->add('suspension.type = ?', array($this->filterSuspensionType));
|
||||||
|
if ($this->filterUserID !== null) $this->objectList->getConditionBuilder()->add('suspension.userID = ?', array($this->filterUserID));
|
||||||
|
if ($this->filterIssuerUserID !== null) $this->objectList->getConditionBuilder()->add('suspension.issuer = ?', array($this->filterIssuerUserID));
|
||||||
|
if ($this->filterRoomID !== null) {
|
||||||
|
if ($this->filterRoomID === 0) {
|
||||||
|
$this->objectList->getConditionBuilder()->add('suspension.roomID IS NULL', array());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->objectList->getConditionBuilder()->add('suspension.roomID = ?', array($this->filterRoomID));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
141
file/lib/acp/page/MessageLogDownloadPage.class.php
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\acp\page;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles text/plain download of chat log.
|
||||||
|
*
|
||||||
|
* @author Maximilian Mader
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage acp.page
|
||||||
|
*/
|
||||||
|
class MessageLogDownloadPage extends \wcf\page\AbstractPage {
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::$activeMenuItem
|
||||||
|
*/
|
||||||
|
public $activeMenuItem = 'chat.acp.menu.link.log';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::$neededPermissions
|
||||||
|
*/
|
||||||
|
public $neededPermissions = array(
|
||||||
|
'admin.chat.canReadLog'
|
||||||
|
);
|
||||||
|
|
||||||
|
public $useTemplate = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* messages for the given day
|
||||||
|
*
|
||||||
|
* @var array<\chat\data\message\Message>
|
||||||
|
*/
|
||||||
|
public $messages = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* given roomID
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public $roomID = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* given date
|
||||||
|
*
|
||||||
|
* @var \DateTime
|
||||||
|
*/
|
||||||
|
public $date = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* active room
|
||||||
|
*
|
||||||
|
* @var \chat\data\room\Room
|
||||||
|
*/
|
||||||
|
public $room = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* available rooms
|
||||||
|
*
|
||||||
|
* @var array<\chat\data\room\Room>
|
||||||
|
*/
|
||||||
|
public $rooms = array();
|
||||||
|
|
||||||
|
public $tmpFile = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\IPage::readData()
|
||||||
|
*/
|
||||||
|
public function readData() {
|
||||||
|
parent::readData();
|
||||||
|
|
||||||
|
$now = new \DateTime('now', WCF::getUser()->getTimeZone());
|
||||||
|
if ($this->date->getTimestamp() > $now->getTimestamp()) {
|
||||||
|
throw new \wcf\system\exception\IllegalLinkException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$oldest = new \DateTime('today -'.ceil(CHAT_LOG_ARCHIVETIME / 1440).'day', WCF::getUser()->getTimeZone());
|
||||||
|
if (CHAT_LOG_ARCHIVETIME !== -1 && $this->date->getTimestamp() < $oldest->getTimestamp()) {
|
||||||
|
throw new \wcf\system\exception\IllegalLinkException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->tmpFile = \wcf\util\FileUtil::getTemporaryFilename();
|
||||||
|
touch($this->tmpFile);
|
||||||
|
\wcf\util\FileUtil::makeWritable($this->tmpFile);
|
||||||
|
|
||||||
|
if (is_writable($this->tmpFile)) {
|
||||||
|
$file = new \wcf\system\io\File($this->tmpFile);
|
||||||
|
$file->write(WCF::getLanguage()->get('chat.acp.log.title') . ': ' . (string) $this->room . "\n");
|
||||||
|
|
||||||
|
for ($start = $this->date->getTimestamp(), $end = $this->date->add(\DateInterval::createFromDateString('1day'))->sub(\DateInterval::createFromDateString('1second'))->getTimestamp(); $start < $end; $start += 1800) {
|
||||||
|
$file->write(WCF::getTpl()->fetch('messageLogDownload', 'chat', array('messages' => \chat\data\message\MessageList::getMessagesBetween($this->room, $start, $start + 1799))));
|
||||||
|
}
|
||||||
|
|
||||||
|
$file->close();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new \wcf\system\exception\IllegalLinkException();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\IPage::readParameters()
|
||||||
|
*/
|
||||||
|
public function readParameters() {
|
||||||
|
parent::readParameters();
|
||||||
|
|
||||||
|
if (isset($_REQUEST['id'])) {
|
||||||
|
$this->roomID = intval($_REQUEST['id']);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new \wcf\system\exception\IllegalLinkException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->room = \chat\data\room\RoomCache::getInstance()->getRoom($this->roomID);
|
||||||
|
if (!$this->room) throw new \wcf\system\exception\IllegalLinkException();
|
||||||
|
if (!$this->room->permanent) throw new \wcf\system\exception\PermissionDeniedException();
|
||||||
|
|
||||||
|
if (isset($_REQUEST['date'])) $date = $_REQUEST['date'].' 00:00:00';
|
||||||
|
else $date = 'today 00:00:00';
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->date = new \DateTime($date, WCF::getUser()->getTimeZone());
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
throw new \wcf\system\exception\IllegalLinkException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see wcf\page\IPage::show()
|
||||||
|
*/
|
||||||
|
public function show() {
|
||||||
|
parent::show();
|
||||||
|
|
||||||
|
$fileReader = new \wcf\util\FileReader($this->tmpFile, array('mimeType' => 'text/plain', 'filename' => str_replace(' ', '-', WCF::getLanguage()->get('chat.acp.log.title') . ' ' . $this->room.'-'.\wcf\util\DateUtil::format($this->date, 'Y-m-d').'.txt')));
|
||||||
|
$fileReader->send();
|
||||||
|
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
130
file/lib/acp/page/MessageLogPage.class.php
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\acp\page;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists chat log.
|
||||||
|
*
|
||||||
|
* @author Maximilian Mader
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage acp.page
|
||||||
|
*/
|
||||||
|
class MessageLogPage extends \wcf\page\AbstractPage {
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::$activeMenuItem
|
||||||
|
*/
|
||||||
|
public $activeMenuItem = 'chat.acp.menu.link.log';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::$neededPermissions
|
||||||
|
*/
|
||||||
|
public $neededPermissions = array(
|
||||||
|
'admin.chat.canReadLog'
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* name of error field
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $errorField = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* error type
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $errorType = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* given roomID
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public $roomID = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* given date
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public $date = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* active room
|
||||||
|
*
|
||||||
|
* @var \chat\data\room\Room
|
||||||
|
*/
|
||||||
|
public $room = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* available rooms
|
||||||
|
*
|
||||||
|
* @var array<\chat\data\room\Room>
|
||||||
|
*/
|
||||||
|
public $rooms = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\IPage::readData()
|
||||||
|
*/
|
||||||
|
public function readData() {
|
||||||
|
parent::readData();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ($this->date > TIME_NOW) {
|
||||||
|
throw new \wcf\system\exception\UserInputException('date', 'inFuture');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CHAT_LOG_ARCHIVETIME !== -1 && $this->date < strtotime('today 00:00:00 -'.ceil(CHAT_LOG_ARCHIVETIME / 1440).'day')) {
|
||||||
|
throw new \wcf\system\exception\UserInputException('date', 'tooLongAgo');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\wcf\system\exception\UserInputException $e) {
|
||||||
|
$this->errorField = $e->getField();
|
||||||
|
$this->errorType = $e->getType();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\IPage::readParameters()
|
||||||
|
*/
|
||||||
|
public function readParameters() {
|
||||||
|
parent::readParameters();
|
||||||
|
|
||||||
|
$this->rooms = \chat\data\room\RoomCache::getInstance()->getRooms();
|
||||||
|
|
||||||
|
foreach ($this->rooms as $id => $room) {
|
||||||
|
if (!$room->permanent) unset($this->rooms[$id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($_REQUEST['id'])) $this->roomID = intval($_REQUEST['id']);
|
||||||
|
else $this->roomID = reset($this->rooms)->roomID;
|
||||||
|
|
||||||
|
$this->room = \chat\data\room\RoomCache::getInstance()->getRoom($this->roomID);
|
||||||
|
|
||||||
|
if (!$this->room) throw new \wcf\system\exception\IllegalLinkException();
|
||||||
|
if (!$this->room->permanent) throw new \wcf\system\exception\PermissionDeniedException();
|
||||||
|
|
||||||
|
if (isset($_REQUEST['date'])) $date = $_REQUEST['date'].' 00:00:00';
|
||||||
|
else $date = 'today 00:00:00';
|
||||||
|
$this->date = @strtotime($date);
|
||||||
|
if ($this->date === false) throw new \wcf\system\exception\IllegalLinkException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see wcf\page\IPage::assignVariables()
|
||||||
|
*/
|
||||||
|
public function assignVariables() {
|
||||||
|
parent::assignVariables();
|
||||||
|
|
||||||
|
WCF::getTPL()->assign(array(
|
||||||
|
'rooms' => $this->rooms,
|
||||||
|
'room' => $this->room,
|
||||||
|
'date' => $this->date,
|
||||||
|
'errorField' => $this->errorField,
|
||||||
|
'errorType' => $this->errorType
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
56
file/lib/acp/page/RoomListPage.class.php
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\acp\page;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists available chatrooms.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage acp.page
|
||||||
|
*/
|
||||||
|
class RoomListPage extends \wcf\page\AbstractPage {
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::$activeMenuItem
|
||||||
|
*/
|
||||||
|
public $activeMenuItem = 'chat.acp.menu.link.room.list';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::$neededPermissions
|
||||||
|
*/
|
||||||
|
public $neededPermissions = array(
|
||||||
|
'admin.chat.canEditRoom',
|
||||||
|
'admin.chat.canDeleteRoom'
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* room list
|
||||||
|
* @var \chat\data\room\RoomListPage
|
||||||
|
*/
|
||||||
|
public $objects = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\IPage::readData()
|
||||||
|
*/
|
||||||
|
public function readData() {
|
||||||
|
parent::readData();
|
||||||
|
|
||||||
|
$this->objects = new \chat\data\room\RoomList();
|
||||||
|
$this->objects->sqlOrderBy = 'showOrder ASC';
|
||||||
|
$this->objects->getConditionBuilder()->add('permanent = ?', array(1));
|
||||||
|
$this->objects->readObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see wcf\page\IPage::assignVariables()
|
||||||
|
*/
|
||||||
|
public function assignVariables() {
|
||||||
|
parent::assignVariables();
|
||||||
|
|
||||||
|
WCF::getTPL()->assign(array(
|
||||||
|
'objects' => $this->objects
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
20
file/lib/data/CHATDatabaseObject.class.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic implementation that sets proper table name.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage data
|
||||||
|
*/
|
||||||
|
abstract class CHATDatabaseObject extends \wcf\data\DatabaseObject {
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\DatabaseObject::getDatabaseTableName()
|
||||||
|
*/
|
||||||
|
public static function getDatabaseTableName() {
|
||||||
|
return 'chat'.WCF_N.'_'.static::$databaseTableName;
|
||||||
|
}
|
||||||
|
}
|
170
file/lib/data/message/Message.class.php
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\data\message;
|
||||||
|
use \chat\util\ChatUtil;
|
||||||
|
use \wcf\system\bbcode\AttachmentBBCode;
|
||||||
|
use \wcf\system\Regex;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a chat message.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage data.message
|
||||||
|
*/
|
||||||
|
class Message extends \chat\data\CHATDatabaseObject {
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\DatabaseObject::$databaseTableName
|
||||||
|
*/
|
||||||
|
protected static $databaseTableName = 'message';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\DatabaseObject::$databaseTableIndexName
|
||||||
|
*/
|
||||||
|
protected static $databaseTableIndexName = 'messageID';
|
||||||
|
|
||||||
|
const TYPE_NORMAL = 0;
|
||||||
|
const TYPE_JOIN = 1;
|
||||||
|
const TYPE_LEAVE = 2;
|
||||||
|
const TYPE_AWAY = 3;
|
||||||
|
const TYPE_BACK = 4;
|
||||||
|
const TYPE_MODERATE = 5;
|
||||||
|
const TYPE_ME = 6;
|
||||||
|
const TYPE_WHISPER = 7;
|
||||||
|
const TYPE_INFORMATION = 8;
|
||||||
|
const TYPE_CLEAR = 9;
|
||||||
|
const TYPE_TEAM = 10;
|
||||||
|
const TYPE_GLOBALMESSAGE = 11;
|
||||||
|
const TYPE_ATTACHMENT = 12;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cache for users
|
||||||
|
* @var array<\wcf\data\user\User>
|
||||||
|
*/
|
||||||
|
protected static $users = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\DatabaseObject::handleData()
|
||||||
|
*/
|
||||||
|
protected function handleData($data) {
|
||||||
|
parent::handleData($data);
|
||||||
|
|
||||||
|
if ($this->data['additionalData'] !== null) {
|
||||||
|
$this->data['additionalData'] = unserialize($this->data['additionalData']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\data\message\Message::getFormattedMessage()
|
||||||
|
*/
|
||||||
|
public function __toString() {
|
||||||
|
return $this->getFormattedMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the formatted message.
|
||||||
|
*
|
||||||
|
* @param string $outputType outputtype for messageparser
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getFormattedMessage($type = 'text/html') {
|
||||||
|
$message = $this->message;
|
||||||
|
$messageParser = \wcf\system\bbcode\MessageParser::getInstance();
|
||||||
|
$messageParser->setOutputType($type);
|
||||||
|
|
||||||
|
switch ($this->type) {
|
||||||
|
case self::TYPE_JOIN:
|
||||||
|
case self::TYPE_LEAVE:
|
||||||
|
case self::TYPE_BACK:
|
||||||
|
$message = WCF::getLanguage()->getDynamicVariable('chat.message.'.$this->type, $this->data['additionalData'] ?: array());
|
||||||
|
break;
|
||||||
|
case self::TYPE_AWAY:
|
||||||
|
$message = WCF::getLanguage()->getDynamicVariable('chat.message.'.$this->type, array('message' => $message));
|
||||||
|
break;
|
||||||
|
case self::TYPE_MODERATE:
|
||||||
|
$message = unserialize($message);
|
||||||
|
$message = WCF::getLanguage()->getDynamicVariable('chat.message.'.$this->type.'.'.$message['type'], $message ?: array());
|
||||||
|
|
||||||
|
if ($type === 'text/plain') return $message;
|
||||||
|
$message = $messageParser->parse($message, false, false, true, false);
|
||||||
|
break;
|
||||||
|
case self::TYPE_ATTACHMENT:
|
||||||
|
$attachmentList = new \wcf\data\attachment\GroupedAttachmentList('be.bastelstu.chat.message');
|
||||||
|
$attachmentList->getConditionBuilder()->add('attachment.objectID IN (?)', array($this->messageID));
|
||||||
|
$attachmentList->readObjects();
|
||||||
|
|
||||||
|
AttachmentBBCode::setAttachmentList($attachmentList);
|
||||||
|
AttachmentBBCode::setObjectID($this->messageID);
|
||||||
|
|
||||||
|
$message = $messageParser->parse($message, false, false, true, false);
|
||||||
|
break;
|
||||||
|
case self::TYPE_WHISPER:
|
||||||
|
case self::TYPE_NORMAL:
|
||||||
|
case self::TYPE_ME:
|
||||||
|
default:
|
||||||
|
if ($type === 'text/plain') return $message;
|
||||||
|
|
||||||
|
$message = $messageParser->parse($message, $this->enableSmilies, $this->enableHTML, true, false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the username.
|
||||||
|
*
|
||||||
|
* @param boolean $colored
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getUsername($colored = false) {
|
||||||
|
$username = $this->username;
|
||||||
|
if ($this->type == self::TYPE_INFORMATION) return WCF::getLanguage()->get('chat.global.information');
|
||||||
|
|
||||||
|
if ($colored) {
|
||||||
|
$username = \chat\util\ChatUtil::gradient($username, $this->color1, $this->color2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $username;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this message into json-form.
|
||||||
|
*
|
||||||
|
* @param boolean $raw
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function jsonify($raw = false) {
|
||||||
|
switch ($this->type) {
|
||||||
|
case self::TYPE_WHISPER:
|
||||||
|
case self::TYPE_NORMAL:
|
||||||
|
case self::TYPE_INFORMATION:
|
||||||
|
$separator = ':';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$separator = '';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$array = array(
|
||||||
|
'formattedUsername' => $this->getUsername(true),
|
||||||
|
'formattedMessage' => $this->getFormattedMessage('text/html'),
|
||||||
|
'formattedTime' => \wcf\util\DateUtil::format(\wcf\util\DateUtil::getDateTimeByTimestamp($this->time), 'H:i:s'),
|
||||||
|
'separator' => $separator,
|
||||||
|
'message' => $this->getFormattedMessage('text/plain'),
|
||||||
|
'sender' => (int) $this->sender,
|
||||||
|
'username' => $this->getUsername(),
|
||||||
|
'time' => (int) $this->time,
|
||||||
|
'receiver' => (int) $this->receiver,
|
||||||
|
'type' => (int) $this->type,
|
||||||
|
'roomID' => (int) $this->roomID,
|
||||||
|
'messageID' => (int) $this->messageID,
|
||||||
|
'additionalData' => $this->additionalData
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($raw) return $array;
|
||||||
|
return \wcf\util\JSON::encode($array);
|
||||||
|
}
|
||||||
|
}
|
267
file/lib/data/message/MessageAction.class.php
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\data\message;
|
||||||
|
use chat\data\room;
|
||||||
|
use wcf\system\exception\UserInputException;
|
||||||
|
use wcf\system\WCF;
|
||||||
|
use wcf\util\MessageUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes message related actions.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage chat.message
|
||||||
|
*/
|
||||||
|
class MessageAction extends \wcf\data\AbstractDatabaseObjectAction {
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\AbstractDatabaseObjectAction::$className
|
||||||
|
*/
|
||||||
|
protected $className = '\chat\data\message\MessageEditor';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes old messages.
|
||||||
|
*
|
||||||
|
* @return integer Number of deleted messages.
|
||||||
|
*/
|
||||||
|
public function prune() {
|
||||||
|
if (CHAT_LOG_ARCHIVETIME == -1) return 0;
|
||||||
|
|
||||||
|
$sql = "SELECT
|
||||||
|
".call_user_func(array($this->className, 'getDatabaseTableIndexName'))."
|
||||||
|
FROM
|
||||||
|
".call_user_func(array($this->className, 'getDatabaseTableName'))."
|
||||||
|
WHERE
|
||||||
|
time < ?";
|
||||||
|
$stmt = \wcf\system\WCF::getDB()->prepareStatement($sql);
|
||||||
|
$stmt->execute(array(TIME_NOW - CHAT_LOG_ARCHIVETIME * 60));
|
||||||
|
|
||||||
|
$objectIDs = array();
|
||||||
|
while ($objectID = $stmt->fetchColumn()) $objectIDs[] = $objectID;
|
||||||
|
|
||||||
|
return call_user_func(array($this->className, 'deleteAll'), $objectIDs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates message sending.
|
||||||
|
*/
|
||||||
|
public function validateSend() {
|
||||||
|
// read user data
|
||||||
|
$this->parameters['userData']['color1'] = WCF::getUser()->chatColor1;
|
||||||
|
$this->parameters['userData']['color2'] = WCF::getUser()->chatColor2;
|
||||||
|
$this->parameters['userData']['roomID'] = WCF::getUser()->chatRoomID;
|
||||||
|
$this->parameters['userData']['away'] = WCF::getUser()->chatAway;
|
||||||
|
|
||||||
|
// read and validate room
|
||||||
|
$this->parameters['room'] = room\RoomCache::getInstance()->getRoom($this->parameters['userData']['roomID']);
|
||||||
|
if ($this->parameters['room'] === null) throw new \wcf\system\exception\IllegalLinkException();
|
||||||
|
if (!$this->parameters['room']->canEnter()) throw new \wcf\system\exception\PermissionDeniedException();
|
||||||
|
if (!$this->parameters['room']->canWrite()) throw new \wcf\system\exception\PermissionDeniedException();
|
||||||
|
|
||||||
|
// read parameters
|
||||||
|
$this->readString('text');
|
||||||
|
$this->readBoolean('enableSmilies', true);
|
||||||
|
$this->parameters['text'] = MessageUtil::stripCrap($this->parameters['text']);
|
||||||
|
$this->parameters['enableHTML'] = false;
|
||||||
|
|
||||||
|
// validate text
|
||||||
|
if (mb_strlen($this->parameters['text']) > CHAT_MAX_LENGTH) throw new UserInputException('text', 'tooLong');
|
||||||
|
|
||||||
|
// search for disallowed bbcodes
|
||||||
|
$disallowedBBCodes = \wcf\system\bbcode\BBCodeParser::getInstance()->validateBBCodes($this->parameters['text'], explode(',', WCF::getSession()->getPermission('user.chat.allowedBBCodes')));
|
||||||
|
if (!empty($disallowedBBCodes)) {
|
||||||
|
throw new UserInputException('text', WCF::getLanguage()->getDynamicVariable('wcf.message.error.disallowedBBCodes', array('disallowedBBCodes' => $disallowedBBCodes)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// search for censored words
|
||||||
|
if (ENABLE_CENSORSHIP) {
|
||||||
|
$result = \wcf\system\message\censorship\Censorship::getInstance()->test($this->parameters['text']);
|
||||||
|
if ($result) {
|
||||||
|
throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('wcf.message.error.censoredWordsFound', array('censoredWords' => $result)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$editor = new \wcf\data\user\UserEditor(WCF::getUser());
|
||||||
|
$editor->update(array(
|
||||||
|
'chatAway' => null,
|
||||||
|
'chatLastActivity' => TIME_NOW
|
||||||
|
));
|
||||||
|
|
||||||
|
// mark user as back
|
||||||
|
if ($this->parameters['userData']['away'] !== null) {
|
||||||
|
$messageAction = new MessageAction(array(), 'create', array(
|
||||||
|
'data' => array(
|
||||||
|
'roomID' => $this->parameters['room']->roomID,
|
||||||
|
'sender' => WCF::getUser()->userID,
|
||||||
|
'username' => WCF::getUser()->username,
|
||||||
|
'time' => TIME_NOW,
|
||||||
|
'type' => Message::TYPE_BACK,
|
||||||
|
'message' => '',
|
||||||
|
'color1' => $this->parameters['userData']['color1'],
|
||||||
|
'color2' => $this->parameters['userData']['color2']
|
||||||
|
)
|
||||||
|
));
|
||||||
|
$messageAction->executeAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle commands
|
||||||
|
$commandHandler = new \chat\system\command\CommandHandler($this->parameters['text'], $this->parameters['room']);
|
||||||
|
if ($commandHandler->isCommand()) {
|
||||||
|
try {
|
||||||
|
$command = $commandHandler->loadCommand();
|
||||||
|
|
||||||
|
if ($command->enableSmilies != \chat\system\command\ICommand::SETTING_USER) $this->parameters['enableSmilies'] = $command->enableSmilies;
|
||||||
|
$this->parameters['enableHTML'] = $command->enableHTML;
|
||||||
|
|
||||||
|
$this->parameters['type'] = $command->getType();
|
||||||
|
$this->parameters['text'] = $command->getMessage();
|
||||||
|
$this->parameters['receiver'] = $command->getReceiver();
|
||||||
|
$this->parameters['additionalData'] = $command->getAdditionalData();
|
||||||
|
}
|
||||||
|
catch (\chat\system\command\NotFoundException $e) {
|
||||||
|
throw new UserInputException('text', WCF::getLanguage()->getDynamicVariable('chat.error.notFound', array('exception' => $e)));
|
||||||
|
}
|
||||||
|
catch (\chat\system\command\UserNotFoundException $e) {
|
||||||
|
throw new UserInputException('text', WCF::getLanguage()->getDynamicVariable('chat.error.userNotFound', array('exception' => $e)));
|
||||||
|
}
|
||||||
|
catch (\InvalidArgumentException $e) {
|
||||||
|
throw new UserInputException('text', WCF::getLanguage()->getDynamicVariable('chat.error.invalidArgument', array('exception' => $e)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->parameters['type'] = Message::TYPE_NORMAL;
|
||||||
|
$this->parameters['receiver'] = null;
|
||||||
|
$this->parameters['additionalData'] = null;
|
||||||
|
|
||||||
|
$this->parameters['text'] = \wcf\system\bbcode\PreParser::getInstance()->parse($this->parameters['text'], explode(',', WCF::getSession()->getPermission('user.chat.allowedBBCodes')));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates sent message.
|
||||||
|
*/
|
||||||
|
public function send() {
|
||||||
|
$this->objectAction = new MessageAction(array(), 'create', array(
|
||||||
|
'data' => array(
|
||||||
|
'roomID' => $this->parameters['room']->roomID,
|
||||||
|
'sender' => WCF::getUser()->userID,
|
||||||
|
'username' => WCF::getUser()->username,
|
||||||
|
'receiver' => $this->parameters['receiver'],
|
||||||
|
'time' => TIME_NOW,
|
||||||
|
'type' => $this->parameters['type'],
|
||||||
|
'message' => $this->parameters['text'],
|
||||||
|
'enableSmilies' => $this->parameters['enableSmilies'] ? 1 : 0,
|
||||||
|
'enableHTML' => $this->parameters['enableHTML'] ? 1 : 0,
|
||||||
|
'color1' => $this->parameters['userData']['color1'],
|
||||||
|
'color2' => $this->parameters['userData']['color2'],
|
||||||
|
'additionalData' => serialize($this->parameters['additionalData'])
|
||||||
|
)
|
||||||
|
));
|
||||||
|
$this->objectAction->executeAction();
|
||||||
|
$returnValues = $this->objectAction->getReturnValues();
|
||||||
|
|
||||||
|
// add activity points
|
||||||
|
\wcf\system\user\activity\point\UserActivityPointHandler::getInstance()->fireEvent('be.bastelstu.chat.activityPointEvent.message', $returnValues['returnValues']->messageID, WCF::getUser()->userID);
|
||||||
|
|
||||||
|
return $returnValues['returnValues'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates getting messages.
|
||||||
|
*/
|
||||||
|
public function validateGetMessages() {
|
||||||
|
// check permissions
|
||||||
|
WCF::getSession()->checkPermissions(array('admin.chat.canReadLog'));
|
||||||
|
|
||||||
|
// read parameters
|
||||||
|
$this->readInteger('roomID');
|
||||||
|
$this->readInteger('start');
|
||||||
|
$this->readInteger('end');
|
||||||
|
|
||||||
|
// read and validate room
|
||||||
|
$this->parameters['room'] = room\RoomCache::getInstance()->getRoom($this->parameters['roomID']);
|
||||||
|
if ($this->parameters['room'] === null) throw new \wcf\system\exception\IllegalLinkException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches messages in between the specified timestamps.
|
||||||
|
*
|
||||||
|
* @return array Array containing message table, containerID and information about an empty message table.
|
||||||
|
*/
|
||||||
|
public function getMessages() {
|
||||||
|
// read messages
|
||||||
|
$messages = ViewableMessageList::getMessagesBetween($this->parameters['room'], $this->parameters['start'], $this->parameters['end']);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'noMessages' => (count($messages) == 0) ? true : null,
|
||||||
|
'containerID' => $this->parameters['containerID'],
|
||||||
|
'template' => WCF::getTPL()->fetch('__messageLogTable', 'chat', array('messages' => $messages), true)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates setting an attachment.
|
||||||
|
*/
|
||||||
|
public function validateSendAttachment() {
|
||||||
|
// read user data
|
||||||
|
$this->parameters['userData']['color1'] = WCF::getUser()->chatColor1;
|
||||||
|
$this->parameters['userData']['color2'] = WCF::getUser()->chatColor2;
|
||||||
|
$this->parameters['userData']['roomID'] = WCF::getUser()->chatRoomID;
|
||||||
|
$this->parameters['userData']['away'] = WCF::getUser()->chatAway;
|
||||||
|
|
||||||
|
// read and validate room
|
||||||
|
$this->parameters['room'] = room\RoomCache::getInstance()->getRoom($this->parameters['userData']['roomID']);
|
||||||
|
if ($this->parameters['room'] === null) throw new \wcf\system\exception\IllegalLinkException();
|
||||||
|
if (!$this->parameters['room']->canEnter()) throw new \wcf\system\exception\PermissionDeniedException();
|
||||||
|
if (!$this->parameters['room']->canWrite()) throw new \wcf\system\exception\PermissionDeniedException();
|
||||||
|
|
||||||
|
$this->readInteger('objectID');
|
||||||
|
if (!$this->parameters['objectID']) throw new \wcf\system\exception\IllegalLinkException();
|
||||||
|
|
||||||
|
$this->readInteger('parentObjectID');
|
||||||
|
if (!$this->parameters['parentObjectID']) throw new \wcf\system\exception\IllegalLinkException();
|
||||||
|
|
||||||
|
$editor = new \wcf\data\user\UserEditor(WCF::getUser());
|
||||||
|
$editor->update(array(
|
||||||
|
'chatAway' => null,
|
||||||
|
'chatLastActivity' => TIME_NOW
|
||||||
|
));
|
||||||
|
|
||||||
|
// mark user as back
|
||||||
|
if ($this->parameters['userData']['away'] !== null) {
|
||||||
|
$messageAction = new MessageAction(array(), 'create', array(
|
||||||
|
'data' => array(
|
||||||
|
'roomID' => $this->parameters['room']->roomID,
|
||||||
|
'sender' => WCF::getUser()->userID,
|
||||||
|
'username' => WCF::getUser()->username,
|
||||||
|
'time' => TIME_NOW,
|
||||||
|
'type' => Message::TYPE_BACK,
|
||||||
|
'message' => '',
|
||||||
|
'color1' => $this->parameters['userData']['color1'],
|
||||||
|
'color2' => $this->parameters['userData']['color2']
|
||||||
|
)
|
||||||
|
));
|
||||||
|
$messageAction->executeAction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a message linked to an attachment
|
||||||
|
*/
|
||||||
|
public function sendAttachment() {
|
||||||
|
$this->parameters['type'] = Message::TYPE_ATTACHMENT;
|
||||||
|
$this->parameters['text'] = '[attach]'. $this->parameters['objectID'] .'[/attach]';
|
||||||
|
$this->parameters['additionalData'] = null;
|
||||||
|
$this->parameters['receiver'] = null;
|
||||||
|
$this->parameters['enableSmilies'] = false;
|
||||||
|
$this->parameters['enableHTML'] = false;
|
||||||
|
|
||||||
|
$messageAction = new MessageAction(array(), 'send', $this->parameters);
|
||||||
|
$messageAction->executeAction();
|
||||||
|
$returnValues = $messageAction->getReturnValues();
|
||||||
|
|
||||||
|
$attachmentHandler = new \wcf\system\attachment\AttachmentHandler('be.bastelstu.chat.message', $this->parameters['objectID'], $this->parameters['tmpHash'], 0);
|
||||||
|
$attachmentHandler->updateObjectID($returnValues['returnValues']->messageID);
|
||||||
|
}
|
||||||
|
}
|
41
file/lib/data/message/MessageEditor.class.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\data\message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides functions to edit chat messages.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage chat.message
|
||||||
|
*/
|
||||||
|
class MessageEditor extends \wcf\data\DatabaseObjectEditor {
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\DatabaseObjectDecorator::$baseClass
|
||||||
|
*/
|
||||||
|
protected static $baseClass = '\chat\data\message\Message';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see wcf\data\DatabaseObjectEditor::deleteAll()
|
||||||
|
*/
|
||||||
|
public static function deleteAll(array $objectIDs = array()) {
|
||||||
|
$count = parent::deleteAll($objectIDs);
|
||||||
|
|
||||||
|
if ($count) {
|
||||||
|
// delete attached files
|
||||||
|
\wcf\system\attachment\AttachmentHandler::removeAttachments('be.bastelstu.chat.message', $objectIDs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify the Push-Server.
|
||||||
|
*/
|
||||||
|
public static function create(array $parameters = array()) {
|
||||||
|
\wcf\system\nodePush\NodePushHandler::getInstance()->sendMessage('be.bastelstu.chat.newMessage');
|
||||||
|
|
||||||
|
return parent::create($parameters);
|
||||||
|
}
|
||||||
|
}
|
82
file/lib/data/message/MessageList.class.php
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\data\message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a list of chat messages.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage chat.room
|
||||||
|
*/
|
||||||
|
class MessageList extends \wcf\data\DatabaseObjectList {
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\DatabaseObjectList::$className
|
||||||
|
*/
|
||||||
|
public $className = 'chat\data\message\Message';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the newest messages for the given room.
|
||||||
|
*
|
||||||
|
* @param \chat\data\room\Room $room
|
||||||
|
* @param integer $number
|
||||||
|
* @return array<\chat\data\message\Message>
|
||||||
|
*/
|
||||||
|
public static function getNewestMessages(\chat\data\room\Room $room, $number = CHAT_LASTMESSAGES) {
|
||||||
|
if ($number === 0) return array();
|
||||||
|
|
||||||
|
$messageList = new static();
|
||||||
|
$messageList->sqlOrderBy = "message.messageID DESC";
|
||||||
|
$messageList->sqlLimit = $number;
|
||||||
|
$messageList->getConditionBuilder()->add('message.receiver IS NULL', array());
|
||||||
|
$messageList->getConditionBuilder()->add('message.roomID = ?', array($room->roomID));
|
||||||
|
|
||||||
|
$messageList->readObjects();
|
||||||
|
return array_reverse($messageList->getObjects());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the messages since the given message-id for the given room.
|
||||||
|
*
|
||||||
|
* @param \chat\data\room\Room $room
|
||||||
|
* @param integer $since
|
||||||
|
* @return array<\chat\data\message\Message>
|
||||||
|
*/
|
||||||
|
public static function getMessagesSince(\chat\data\room\Room $room, $since) {
|
||||||
|
$messageList = new static();
|
||||||
|
$messageList->sqlOrderBy = "message.messageID ASC";
|
||||||
|
$messageList->getConditionBuilder()->add('message.messageID > ?', array($since));
|
||||||
|
$messageList->getConditionBuilder()->add('
|
||||||
|
((
|
||||||
|
message.receiver IS NULL
|
||||||
|
AND message.roomID = ?
|
||||||
|
)
|
||||||
|
OR message.receiver = ?
|
||||||
|
OR message.sender = ?)',
|
||||||
|
array($room->roomID, \wcf\system\WCF::getUser()->userID, \wcf\system\WCF::getUser()->userID)
|
||||||
|
);
|
||||||
|
|
||||||
|
$messageList->readObjects();
|
||||||
|
return $messageList->getObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the message between the given timestamps for the given room.
|
||||||
|
*
|
||||||
|
* @param \chat\data\room\Room $room
|
||||||
|
* @param integer $start
|
||||||
|
* @param integer $end
|
||||||
|
* @return array<\chat\data\message\Message>
|
||||||
|
*/
|
||||||
|
public static function getMessagesBetween(\chat\data\room\Room $room, $start, $end) {
|
||||||
|
$messageList = new static();
|
||||||
|
$messageList->sqlOrderBy = "message.messageID ASC";
|
||||||
|
$messageList->getConditionBuilder()->add('message.receiver IS NULL', array());
|
||||||
|
$messageList->getConditionBuilder()->add('message.roomID = ?', array($room->roomID));
|
||||||
|
$messageList->getConditionBuilder()->add('message.time BETWEEN ? AND ?', array($start, $end));
|
||||||
|
|
||||||
|
$messageList->readObjects();
|
||||||
|
return $messageList->getObjects();
|
||||||
|
}
|
||||||
|
}
|
54
file/lib/data/message/ViewableMessage.class.php
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\data\message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a viewable chat message.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage data.message
|
||||||
|
*/
|
||||||
|
class ViewableMessage extends \wcf\data\DatabaseObjectDecorator {
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\DatabaseObjectDecorator::$baseClass
|
||||||
|
*/
|
||||||
|
protected static $baseClass = 'chat\data\message\Message';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* user profile object
|
||||||
|
* @var \wcf\data\user\UserProfile
|
||||||
|
*/
|
||||||
|
protected $userProfile = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the profile object of the user who created the post.
|
||||||
|
*
|
||||||
|
* @return wcf\data\user\UserProfile
|
||||||
|
*/
|
||||||
|
public function getUserProfile() {
|
||||||
|
if ($this->userProfile === null) {
|
||||||
|
$this->userProfile = new \wcf\data\user\UserProfile(new \wcf\data\user\User(null, $this->getDecoratedObject()->data));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->userProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\data\message\Message::jsonify()
|
||||||
|
*/
|
||||||
|
public function jsonify($raw = false) {
|
||||||
|
$array = parent::jsonify(true);
|
||||||
|
|
||||||
|
$array['avatar'] = array(
|
||||||
|
16 => $this->getUserProfile()->getAvatar()->getImageTag(16),
|
||||||
|
24 => $this->getUserProfile()->getAvatar()->getImageTag(24),
|
||||||
|
32 => $this->getUserProfile()->getAvatar()->getImageTag(32),
|
||||||
|
48 => $this->getUserProfile()->getAvatar()->getImageTag(48)
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($raw) return $array;
|
||||||
|
return \wcf\util\JSON::encode($array);
|
||||||
|
}
|
||||||
|
}
|
35
file/lib/data/message/ViewableMessageList.class.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\data\message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a list of viewable chat messages.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage chat.room
|
||||||
|
*/
|
||||||
|
class ViewableMessageList extends MessageList {
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\DatabaseObjectList::$decoratorClassName
|
||||||
|
*/
|
||||||
|
public $decoratorClassName = 'chat\data\message\ViewableMessage';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\DatabaseObjectList::__construct()
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
|
$this->sqlSelects .= "user_avatar.*, user_option_value.*, user_table.*";
|
||||||
|
$this->sqlJoins .= " LEFT JOIN wcf".WCF_N."_user user_table ON (user_table.userID = message.sender)";
|
||||||
|
$this->sqlJoins .= " LEFT JOIN wcf".WCF_N."_user_avatar user_avatar ON (user_avatar.avatarID = user_table.avatarID)";
|
||||||
|
$this->sqlJoins .= " LEFT JOIN wcf".WCF_N."_user_option_value user_option_value ON (user_option_value.userID = user_table.userID)";
|
||||||
|
|
||||||
|
if (MODULE_USER_RANK) {
|
||||||
|
$this->sqlSelects .= ",user_rank.*";
|
||||||
|
$this->sqlJoins .= " LEFT JOIN wcf".WCF_N."_user_rank user_rank ON (user_rank.rankID = user_table.rankID)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
213
file/lib/data/room/Room.class.php
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\data\room;
|
||||||
|
use \chat\data\suspension\Suspension;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a chat room.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage data.room
|
||||||
|
*/
|
||||||
|
class Room extends \chat\data\CHATDatabaseObject implements \wcf\system\request\IRouteController {
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\DatabaseObject::$databaseTableName
|
||||||
|
*/
|
||||||
|
protected static $databaseTableName = 'room';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\DatabaseObject::$databaseTableIndexName
|
||||||
|
*/
|
||||||
|
protected static $databaseTableIndexName = 'roomID';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cached users
|
||||||
|
*
|
||||||
|
* @var array<\wcf\data\user\UserProfile>
|
||||||
|
*/
|
||||||
|
protected static $users = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\chat\room\ChatRoom::getTitle();
|
||||||
|
*/
|
||||||
|
public function __toString() {
|
||||||
|
return $this->getTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the user is allowed to enter the room.
|
||||||
|
*
|
||||||
|
* @param \wcf\data\user\User $user
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function canEnter(\wcf\data\user\User $user = null) {
|
||||||
|
if ($user === null) $user = WCF::getUser();
|
||||||
|
if (!$user->userID) return false;
|
||||||
|
$user = new \wcf\data\user\UserProfile($user);
|
||||||
|
|
||||||
|
if ($this->isPermanent && $user->getPermission('admin.chat.canManageSuspensions')) return true;
|
||||||
|
if ($this->isPermanent && $user->getPermission('mod.chat.canGban')) return true;
|
||||||
|
|
||||||
|
$ph = new \chat\system\permission\PermissionHandler($user->getDecoratedObject());
|
||||||
|
if ($ph->getPermission($this, 'mod.canAlwaysEnter')) return true;
|
||||||
|
if ($ph->getPermission($this, 'mod.canBan')) return true;
|
||||||
|
|
||||||
|
if (!$ph->getPermission($this, 'user.canEnter')) return false;
|
||||||
|
|
||||||
|
$suspensions = Suspension::getSuspensionsForUser($user->getDecoratedObject());
|
||||||
|
// room suspension
|
||||||
|
if (isset($suspensions[$this->roomID][Suspension::TYPE_BAN])) {
|
||||||
|
if ($suspensions[$this->roomID][Suspension::TYPE_BAN]->isValid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// global suspension
|
||||||
|
if (isset($suspensions[null][Suspension::TYPE_BAN])) {
|
||||||
|
if ($suspensions[null][Suspension::TYPE_BAN]->isValid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the user is allowed to write messages in this room.
|
||||||
|
*
|
||||||
|
* @param \wcf\data\user\User $user
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function canWrite(\wcf\data\user\User $user = null) {
|
||||||
|
if ($user === null) $user = WCF::getUser();
|
||||||
|
if (!$user->userID) return false;
|
||||||
|
$user = new \wcf\data\user\UserProfile($user);
|
||||||
|
|
||||||
|
if ($user->getPermission('admin.chat.canManageSuspensions')) return true;
|
||||||
|
if ($user->getPermission('mod.chat.canGmute')) return true;
|
||||||
|
|
||||||
|
$ph = new \chat\system\permission\PermissionHandler($user->getDecoratedObject());
|
||||||
|
if ($ph->getPermission($this, 'mod.canAlwaysWrite')) return true;
|
||||||
|
if ($ph->getPermission($this, 'mod.canMute')) return true;
|
||||||
|
|
||||||
|
if (!$ph->getPermission($this, 'user.canWrite')) return false;
|
||||||
|
|
||||||
|
$suspensions = Suspension::getSuspensionsForUser($user->getDecoratedObject());
|
||||||
|
// room suspension
|
||||||
|
if (isset($suspensions[$this->roomID][Suspension::TYPE_MUTE])) {
|
||||||
|
if ($suspensions[$this->roomID][Suspension::TYPE_MUTE]->isValid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// global suspension
|
||||||
|
if (isset($suspensions[null][Suspension::TYPE_MUTE])) {
|
||||||
|
if ($suspensions[null][Suspension::TYPE_MUTE]->isValid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the user is allowed to mute other users in this room.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function canMute() {
|
||||||
|
if (WCF::getSession()->getPermission('admin.chat.canManageSuspensions')) return true;
|
||||||
|
if (WCF::getSession()->getPermission('mod.chat.canGmute')) return true;
|
||||||
|
|
||||||
|
$ph = new \chat\system\permission\PermissionHandler();
|
||||||
|
return $ph->getPermission($this, 'mod.canMute');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the user is allowed to ban other users in this room.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function canBan() {
|
||||||
|
if (WCF::getSession()->getPermission('admin.chat.canManageSuspensions')) return true;
|
||||||
|
if (WCF::getSession()->getPermission('mod.chat.canGban')) return true;
|
||||||
|
|
||||||
|
$ph = new \chat\system\permission\PermissionHandler();
|
||||||
|
return $ph->getPermission($this, 'mod.canBan');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the ID of this chatroom.
|
||||||
|
*
|
||||||
|
* @see \wcf\system\request\IRouteController
|
||||||
|
*/
|
||||||
|
public function getID() {
|
||||||
|
return $this->roomID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of this chatroom.
|
||||||
|
*
|
||||||
|
* @see \wcf\system\request\IRouteController
|
||||||
|
*/
|
||||||
|
public function getTitle() {
|
||||||
|
return \wcf\system\WCF::getLanguage()->get($this->title);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the topic of this chat room
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getTopic() {
|
||||||
|
return \wcf\system\WCF::getLanguage()->get($this->topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the users that are currently active in this room.
|
||||||
|
*
|
||||||
|
* @return array<\wcf\data\user\UserProfile>
|
||||||
|
*/
|
||||||
|
public function getUsers() {
|
||||||
|
if (self::$users === null) {
|
||||||
|
$userList = new \wcf\data\user\UserProfileList();
|
||||||
|
$userList->getConditionBuilder()->add('user_table.chatRoomID IS NOT NULL', array());
|
||||||
|
|
||||||
|
$userList->readObjects();
|
||||||
|
$users = $userList->getObjects();
|
||||||
|
|
||||||
|
foreach ($users as $userID => $user) {
|
||||||
|
if (!isset(self::$users[$user->chatRoomID])) self::$users[$user->chatRoomID] = array();
|
||||||
|
self::$users[$user->chatRoomID][$userID] = $user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isset(self::$users[$this->roomID])) self::$users[$this->roomID] = array();
|
||||||
|
|
||||||
|
return self::$users[$this->roomID];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the users that "timed out".
|
||||||
|
*
|
||||||
|
* @return \wcf\data\user\UserList
|
||||||
|
*/
|
||||||
|
public static function getDeadUsers() {
|
||||||
|
if (\wcf\system\nodePush\NodePushHandler::getInstance()->isEnabled()) {
|
||||||
|
$time = TIME_NOW - 180;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$time = TIME_NOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
$userList = new \wcf\data\user\UserList();
|
||||||
|
$userList->getConditionBuilder()->add('user_table.chatRoomID IS NOT NULL', array());
|
||||||
|
$userList->getConditionBuilder()->add('user_table.chatLastActivity < ?', array($time - 30));
|
||||||
|
|
||||||
|
$userList->readObjects();
|
||||||
|
|
||||||
|
return $userList;
|
||||||
|
}
|
||||||
|
}
|
361
file/lib/data/room/RoomAction.class.php
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\data\room;
|
||||||
|
use \chat\data\message;
|
||||||
|
use \chat\util\ChatUtil;
|
||||||
|
use \wcf\system\exception;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes chatroom-related actions.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage data.room
|
||||||
|
*/
|
||||||
|
class RoomAction extends \wcf\data\AbstractDatabaseObjectAction implements \wcf\data\ISortableAction {
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\AbstractDatabaseObjectAction::$className
|
||||||
|
*/
|
||||||
|
protected $className = '\chat\data\room\RoomEditor';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\AbstractDatabaseObjectAction::$permissionsDelete
|
||||||
|
*/
|
||||||
|
protected $permissionsDelete = array('admin.chat.canDeleteRoom');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\AbstractDatabaseObjectAction::$permissionsUpdate
|
||||||
|
*/
|
||||||
|
protected $permissionsUpdate = array('admin.chat.canEditRoom');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets cache if any of the listed actions is invoked
|
||||||
|
* @var array<string>
|
||||||
|
*/
|
||||||
|
protected $resetCache = array('create', 'delete', 'toggle', 'update', 'updatePosition', 'prune');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fixes create to append new rooms.
|
||||||
|
*/
|
||||||
|
public function create() {
|
||||||
|
$room = parent::create();
|
||||||
|
|
||||||
|
WCF::getDB()->beginTransaction();
|
||||||
|
$sql = "SELECT MAX(showOrder)
|
||||||
|
FROM ".call_user_func(array($this->className, 'getDatabaseTableName'))."
|
||||||
|
FOR UPDATE";
|
||||||
|
$stmt = WCF::getDB()->prepareStatement($sql);
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
$editor = new RoomEditor($room);
|
||||||
|
$editor->update(array('showOrder' => ($stmt->fetchColumn() + 1)));
|
||||||
|
WCF::getDB()->commitTransaction();
|
||||||
|
|
||||||
|
return $room;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes temporary rooms that are unused.
|
||||||
|
*
|
||||||
|
* @return integer Number of deleted rooms
|
||||||
|
*/
|
||||||
|
public function prune() {
|
||||||
|
$sql = "SELECT
|
||||||
|
".call_user_func(array($this->className, 'getDatabaseTableIndexName'))."
|
||||||
|
FROM
|
||||||
|
".call_user_func(array($this->className, 'getDatabaseTableName'))."
|
||||||
|
WHERE
|
||||||
|
permanent = ?
|
||||||
|
AND roomID NOT IN (
|
||||||
|
SELECT chatRoomID
|
||||||
|
FROM wcf".WCF_N."_user
|
||||||
|
WHERE chatRoomID IS NOT NULL
|
||||||
|
)";
|
||||||
|
$stmt = \wcf\system\WCF::getDB()->prepareStatement($sql);
|
||||||
|
$stmt->execute(array(0));
|
||||||
|
$objectIDs = array();
|
||||||
|
|
||||||
|
while ($objectID = $stmt->fetchColumn()) $objectIDs[] = $objectID;
|
||||||
|
|
||||||
|
return call_user_func(array($this->className, 'deleteAll'), $objectIDs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see wcf\data\ISortableAction::validateUpdatePosition()
|
||||||
|
*/
|
||||||
|
public function validateUpdatePosition() {
|
||||||
|
// validate permissions
|
||||||
|
if (is_array($this->permissionsUpdate) && count($this->permissionsUpdate)) {
|
||||||
|
WCF::getSession()->checkPermissions($this->permissionsUpdate);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new exception\PermissionDeniedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($this->parameters['data']['structure'])) {
|
||||||
|
throw new exception\UserInputException('structure');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see wcf\data\ISortableAction::updatePosition()
|
||||||
|
*/
|
||||||
|
public function updatePosition() {
|
||||||
|
$roomList = new RoomList();
|
||||||
|
$roomList->readObjects();
|
||||||
|
|
||||||
|
$i = 0;
|
||||||
|
WCF::getDB()->beginTransaction();
|
||||||
|
foreach ($this->parameters['data']['structure'][0] as $roomID) {
|
||||||
|
$room = $roomList->search($roomID);
|
||||||
|
if ($room === null) continue;
|
||||||
|
|
||||||
|
$editor = new RoomEditor($room);
|
||||||
|
$editor->update(array('showOrder' => $i++));
|
||||||
|
}
|
||||||
|
WCF::getDB()->commitTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates parameters and permissions.
|
||||||
|
*/
|
||||||
|
public function validateGetRoomList() {
|
||||||
|
if (!MODULE_CHAT) throw new exception\IllegalLinkException();
|
||||||
|
|
||||||
|
$this->parameters['room'] = RoomCache::getInstance()->getRoom(WCF::getUser()->chatRoomID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the available rooms.
|
||||||
|
*/
|
||||||
|
public function getRoomList() {
|
||||||
|
$rooms = RoomCache::getInstance()->getRooms();
|
||||||
|
|
||||||
|
$result = array();
|
||||||
|
foreach ($rooms as $room) {
|
||||||
|
if (!$room->canEnter()) continue;
|
||||||
|
|
||||||
|
$result[] = array(
|
||||||
|
'title' => (string) $room,
|
||||||
|
'topic' => $room->getTopic(),
|
||||||
|
'link' => \wcf\system\request\LinkHandler::getInstance()->getLink('Chat', array(
|
||||||
|
'application' => 'chat',
|
||||||
|
'object' => $room
|
||||||
|
)),
|
||||||
|
'roomID' => (int) $room->roomID,
|
||||||
|
'active' => $this->parameters['room'] && $room->roomID == $this->parameters['room']->roomID,
|
||||||
|
'userCount' => count($room->getUsers()),
|
||||||
|
'permissions' => array(
|
||||||
|
'canBan' => (boolean) $room->canBan(),
|
||||||
|
'canMute' => (boolean) $room->canMute()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates parameters and permissions.
|
||||||
|
*/
|
||||||
|
public function validateJoin() {
|
||||||
|
if (!MODULE_CHAT) throw new exception\IllegalLinkException();
|
||||||
|
|
||||||
|
unset($this->parameters['user']);
|
||||||
|
$this->readInteger('roomID');
|
||||||
|
|
||||||
|
$room = RoomCache::getInstance()->getRoom($this->parameters['roomID']);
|
||||||
|
if ($room === null) throw new exception\UserInputException('roomID');
|
||||||
|
if (!$room->canEnter()) throw new exception\PermissionDeniedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Joins the room.
|
||||||
|
*/
|
||||||
|
public function join() {
|
||||||
|
// user cannot be set during an AJAX request but may be set by the chat itself
|
||||||
|
if (!isset($this->parameters['user'])) {
|
||||||
|
$this->parameters['user'] = WCF::getUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
$room = RoomCache::getInstance()->getRoom($this->parameters['roomID']);
|
||||||
|
if ($room === null) throw new exception\UserInputException();
|
||||||
|
|
||||||
|
if (CHAT_DISPLAY_JOIN_LEAVE) {
|
||||||
|
if ($this->parameters['user']->chatRoomID) {
|
||||||
|
// leave message
|
||||||
|
$messageAction = new message\MessageAction(array(), 'create', array(
|
||||||
|
'data' => array(
|
||||||
|
'roomID' => $this->parameters['user']->chatRoomID,
|
||||||
|
'sender' => $this->parameters['user']->userID,
|
||||||
|
'username' => $this->parameters['user']->username,
|
||||||
|
'time' => TIME_NOW,
|
||||||
|
'type' => message\Message::TYPE_LEAVE,
|
||||||
|
'message' => '',
|
||||||
|
'color1' => $this->parameters['user']->chatColor1,
|
||||||
|
'color2' => $this->parameters['user']->chatColor2,
|
||||||
|
'additionalData' => serialize(array('room' => $room))
|
||||||
|
)
|
||||||
|
));
|
||||||
|
$messageAction->executeAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
$ipAddress = '';
|
||||||
|
if (LOG_IP_ADDRESS && $this->parameters['user']->userID == WCF::getUser()->userID) $ipAddress = \wcf\util\UserUtil::convertIPv6To4(\wcf\util\UserUtil::getIpAddress());
|
||||||
|
|
||||||
|
// join message
|
||||||
|
$messageAction = new message\MessageAction(array(), 'create', array(
|
||||||
|
'data' => array(
|
||||||
|
'roomID' => $room->roomID,
|
||||||
|
'sender' => $this->parameters['user']->userID,
|
||||||
|
'username' => $this->parameters['user']->username,
|
||||||
|
'time' => TIME_NOW,
|
||||||
|
'type' => message\Message::TYPE_JOIN,
|
||||||
|
'message' => '',
|
||||||
|
'color1' => $this->parameters['user']->chatColor1,
|
||||||
|
'color2' => $this->parameters['user']->chatColor2,
|
||||||
|
'additionalData' => serialize(array('ipAddress' => $ipAddress))
|
||||||
|
)
|
||||||
|
));
|
||||||
|
$messageAction->executeAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
$newestMessages = message\ViewableMessageList::getNewestMessages($room, CHAT_LASTMESSAGES + CHAT_DISPLAY_JOIN_LEAVE);
|
||||||
|
|
||||||
|
// update last seen message
|
||||||
|
$sql = "SELECT
|
||||||
|
MAX(messageID)
|
||||||
|
FROM
|
||||||
|
chat".WCF_N."_message";
|
||||||
|
$stmt = WCF::getDB()->prepareStatement($sql);
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
$editor = new \wcf\data\user\UserEditor($this->parameters['user']);
|
||||||
|
$editor->update(array(
|
||||||
|
'chatRoomID' => $room->roomID,
|
||||||
|
'chatAway' => null,
|
||||||
|
'chatLastActivity' => TIME_NOW,
|
||||||
|
'chatLastSeen' => $stmt->fetchColumn() ?: 0
|
||||||
|
));
|
||||||
|
|
||||||
|
// add activity points
|
||||||
|
$microtime = microtime(true) * 1000;
|
||||||
|
$result = $microtime & 0xFFFFFFFF;
|
||||||
|
if ($result > 0x7FFFFFFF) $result -= 0x80000000;
|
||||||
|
\wcf\system\user\activity\point\UserActivityPointHandler::getInstance()->fireEvent('be.bastelstu.chat.activityPointEvent.join', $result, WCF::getUser()->userID);
|
||||||
|
|
||||||
|
// send push message about join
|
||||||
|
\wcf\system\nodePush\NodePushHandler::getInstance()->sendMessage('be.bastelstu.chat.join');
|
||||||
|
|
||||||
|
$messages = array();
|
||||||
|
foreach ($newestMessages as $message) $messages[] = $message->jsonify(true);
|
||||||
|
return array(
|
||||||
|
'title' => (string) $room,
|
||||||
|
'topic' => $room->getTopic(),
|
||||||
|
'link' => \wcf\system\request\LinkHandler::getInstance()->getLink('Chat', array(
|
||||||
|
'application' => 'chat',
|
||||||
|
'object' => $room
|
||||||
|
)),
|
||||||
|
'roomID' => (int) $room->roomID,
|
||||||
|
'userCount' => count($room->getUsers()),
|
||||||
|
'permissions' => array(
|
||||||
|
'canBan' => (boolean) $room->canBan(),
|
||||||
|
'canMute' => (boolean) $room->canMute()
|
||||||
|
),
|
||||||
|
'messages' => $messages,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates parameters and permissions.
|
||||||
|
*/
|
||||||
|
public function validateLeave() {
|
||||||
|
if (!MODULE_CHAT) throw new exception\IllegalLinkException();
|
||||||
|
|
||||||
|
unset($this->parameters['user']);
|
||||||
|
|
||||||
|
if (RoomCache::getInstance()->getRoom(WCF::getUser()->chatRoomID) === null) throw new exception\IllegalLinkException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Leaves the room.
|
||||||
|
*/
|
||||||
|
public function leave() {
|
||||||
|
// user cannot be set during an AJAX request but may be set by the chat itself
|
||||||
|
if (!isset($this->parameters['user'])) {
|
||||||
|
$this->parameters['user'] = WCF::getUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
$room = RoomCache::getInstance()->getRoom($this->parameters['user']->chatRoomID);
|
||||||
|
if ($room === null) throw new exception\UserInputException();
|
||||||
|
|
||||||
|
if (CHAT_DISPLAY_JOIN_LEAVE) {
|
||||||
|
// leave message
|
||||||
|
$messageAction = new message\MessageAction(array(), 'create', array(
|
||||||
|
'data' => array(
|
||||||
|
'roomID' => $room->roomID,
|
||||||
|
'sender' => $this->parameters['user']->userID,
|
||||||
|
'username' => $this->parameters['user']->username,
|
||||||
|
'time' => TIME_NOW,
|
||||||
|
'type' => message\Message::TYPE_LEAVE,
|
||||||
|
'message' => '',
|
||||||
|
'color1' => $this->parameters['user']->chatColor1,
|
||||||
|
'color2' => $this->parameters['user']->chatColor2
|
||||||
|
)
|
||||||
|
));
|
||||||
|
$messageAction->executeAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
// set current room to null
|
||||||
|
$editor = new \wcf\data\user\UserEditor($this->parameters['user']);
|
||||||
|
$editor->update(array(
|
||||||
|
'chatRoomID' => null
|
||||||
|
));
|
||||||
|
|
||||||
|
\wcf\system\nodePush\NodePushHandler::getInstance()->sendMessage('be.bastelstu.chat.leave');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forces dead users to leave the chat.
|
||||||
|
*/
|
||||||
|
public function removeDeadUsers() {
|
||||||
|
$deadUsers = Room::getDeadUsers();
|
||||||
|
|
||||||
|
foreach ($deadUsers as $deadUser) {
|
||||||
|
$roomAction = new self(array(), 'leave', array(
|
||||||
|
'user' => $deadUser
|
||||||
|
));
|
||||||
|
$roomAction->executeAction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates permissions.
|
||||||
|
*/
|
||||||
|
public function validateGetBoxRoomList() {
|
||||||
|
if (!MODULE_CHAT) throw new \wcf\system\exception\IllegalLinkException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns dashboard roomlist.
|
||||||
|
*/
|
||||||
|
public function getBoxRoomList() {
|
||||||
|
$rooms = RoomCache::getInstance()->getRooms();
|
||||||
|
|
||||||
|
foreach ($rooms as $key => $room) {
|
||||||
|
if (!$room->canEnter()) unset($rooms[$key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->readBoolean('showEmptyRooms', true);
|
||||||
|
\wcf\system\WCF::getTPL()->assign(array(
|
||||||
|
'rooms' => $rooms,
|
||||||
|
'showEmptyRooms' => $this->parameters['showEmptyRooms']
|
||||||
|
));
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'template' => \wcf\system\WCF::getTPL()->fetch('boxRoomList', 'chat')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
49
file/lib/data/room/RoomCache.class.php
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\data\room;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages the room cache.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage data.room
|
||||||
|
*/
|
||||||
|
class RoomCache extends \wcf\system\SingletonFactory {
|
||||||
|
/**
|
||||||
|
* list of cached rooms
|
||||||
|
* @var array<\chat\data\room\Room>
|
||||||
|
*/
|
||||||
|
protected $rooms = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see wcf\system\SingletonFactory::init()
|
||||||
|
*/
|
||||||
|
protected function init() {
|
||||||
|
$this->rooms = \chat\system\cache\builder\RoomCacheBuilder::getInstance()->getData();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a specific room.
|
||||||
|
*
|
||||||
|
* @param integer $roomID
|
||||||
|
* @return \chat\data\room\Room
|
||||||
|
*/
|
||||||
|
public function getRoom($roomID) {
|
||||||
|
if (isset($this->rooms[$roomID])) {
|
||||||
|
return $this->rooms[$roomID];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all rooms.
|
||||||
|
*
|
||||||
|
* @return array<\chat\data\room\Room>
|
||||||
|
*/
|
||||||
|
public function getRooms() {
|
||||||
|
return $this->rooms;
|
||||||
|
}
|
||||||
|
}
|
68
file/lib/data/room/RoomEditor.class.php
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\data\room;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides functions to edit chat rooms.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage data.room
|
||||||
|
*/
|
||||||
|
class RoomEditor extends \wcf\data\DatabaseObjectEditor implements \wcf\data\IEditableCachedObject {
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\DatabaseObjectDecorator::$baseClass
|
||||||
|
*/
|
||||||
|
protected static $baseClass = '\chat\data\room\Room';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\DatabaseObjectEditor::deleteAll()
|
||||||
|
*/
|
||||||
|
public static function deleteAll(array $objectIDs = array()) {
|
||||||
|
WCF::getDB()->beginTransaction();
|
||||||
|
foreach ($objectIDs as $objectID) {
|
||||||
|
\wcf\system\language\I18nHandler::getInstance()->remove('chat.room.title'.$objectID);
|
||||||
|
\wcf\system\language\I18nHandler::getInstance()->remove('chat.room.topic'.$objectID);
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql = "SELECT
|
||||||
|
showOrder
|
||||||
|
FROM
|
||||||
|
chat".WCF_N."_room
|
||||||
|
WHERE
|
||||||
|
roomID = ?
|
||||||
|
FOR UPDATE";
|
||||||
|
$select = WCF::getDB()->prepareStatement($sql);
|
||||||
|
|
||||||
|
$sql = "UPDATE
|
||||||
|
chat".WCF_N."_room
|
||||||
|
SET
|
||||||
|
showOrder = showOrder - 1
|
||||||
|
WHERE
|
||||||
|
showOrder > ?";
|
||||||
|
$update = WCF::getDB()->prepareStatement($sql);
|
||||||
|
|
||||||
|
foreach ($objectIDs as $objectID) {
|
||||||
|
$select->execute(array($objectID));
|
||||||
|
$showOrder = $select->fetchColumn();
|
||||||
|
$select->closeCursor();
|
||||||
|
$update->execute(array($showOrder));
|
||||||
|
}
|
||||||
|
|
||||||
|
$return = parent::deleteAll($objectIDs);
|
||||||
|
WCF::getDB()->commitTransaction();
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the room cache.
|
||||||
|
*/
|
||||||
|
public static function resetCache() {
|
||||||
|
\chat\system\cache\builder\RoomCacheBuilder::getInstance()->reset();
|
||||||
|
\chat\system\cache\builder\PermissionCacheBuilder::getInstance()->reset();
|
||||||
|
\wcf\system\nodePush\NodePushHandler::getInstance()->sendDeferredMessage('be.bastelstu.chat.roomChange');
|
||||||
|
}
|
||||||
|
}
|
18
file/lib/data/room/RoomList.class.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\data\room;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a list of chat rooms.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage data.room
|
||||||
|
*/
|
||||||
|
class RoomList extends \wcf\data\DatabaseObjectList {
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\DatabaseObjectList::$className
|
||||||
|
*/
|
||||||
|
public $className = 'chat\data\room\Room';
|
||||||
|
}
|
139
file/lib/data/suspension/Suspension.class.php
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\data\suspension;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a chat suspension.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage data.suspension
|
||||||
|
*/
|
||||||
|
class Suspension extends \chat\data\CHATDatabaseObject {
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\DatabaseObject::$databaseTableName
|
||||||
|
*/
|
||||||
|
protected static $databaseTableName = 'suspension';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\DatabaseObject::$databaseTableIndexName
|
||||||
|
*/
|
||||||
|
protected static $databaseTableIndexName = 'suspensionID';
|
||||||
|
|
||||||
|
const TYPE_MUTE = 'mute';
|
||||||
|
const TYPE_BAN = 'ban';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the suspension still is valid.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isValid() {
|
||||||
|
return $this->expires > TIME_NOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given user may view this suspension.
|
||||||
|
*
|
||||||
|
* @param \wcf\data\user\User $user
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isVisible($user = null) {
|
||||||
|
if ($user === null) $user = WCF::getUser();
|
||||||
|
$user = new \wcf\data\user\UserProfile($user);
|
||||||
|
$ph = new \chat\system\permission\PermissionHandler($user->getDecoratedObject());
|
||||||
|
|
||||||
|
if ($user->getPermission('admin.chat.canManageSuspensions')) return true;
|
||||||
|
if ($user->getPermission('mod.chat.canG'.$this->type)) return true;
|
||||||
|
if (!$this->roomID) return false;
|
||||||
|
if ($ph->getPermission($this->getRoom(), 'mod.can'.ucfirst($this->type))) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the room of this suspension.
|
||||||
|
*
|
||||||
|
* @return \chat\data\room\Room
|
||||||
|
*/
|
||||||
|
public function getRoom() {
|
||||||
|
if (!$this->roomID) return new \chat\data\room\Room(null, array('roomID' => null));
|
||||||
|
|
||||||
|
return \chat\data\room\RoomCache::getInstance()->getRoom($this->roomID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the suspensions for the specified user (current user if no user was specified).
|
||||||
|
*
|
||||||
|
* @param \wcf\data\user\User $user
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function getSuspensionsForUser(\wcf\data\user\User $user = null) {
|
||||||
|
if ($user === null) $user = WCF::getUser();
|
||||||
|
$ush = \wcf\system\user\storage\UserStorageHandler::getInstance();
|
||||||
|
|
||||||
|
// load storage
|
||||||
|
$ush->loadStorage(array($user->userID));
|
||||||
|
$data = $ush->getStorage(array($user->userID), 'chatSuspensions');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$suspensions = unserialize($data[$user->userID]);
|
||||||
|
if ($suspensions === false) throw new \wcf\system\exception\SystemException();
|
||||||
|
}
|
||||||
|
catch (\wcf\system\exception\SystemException $e) {
|
||||||
|
$condition = new \wcf\system\database\util\PreparedStatementConditionBuilder();
|
||||||
|
$condition->add('userID = ?', array($user->userID));
|
||||||
|
$condition->add('expires > ?', array(TIME_NOW));
|
||||||
|
|
||||||
|
$sql = "SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
chat".WCF_N."_suspension
|
||||||
|
".$condition;
|
||||||
|
$stmt = WCF::getDB()->prepareStatement($sql);
|
||||||
|
$stmt->execute($condition->getParameters());
|
||||||
|
|
||||||
|
$suspensions = array();
|
||||||
|
while ($suspension = $stmt->fetchObject('\chat\data\suspension\Suspension')) {
|
||||||
|
$suspensions[$suspension->roomID][$suspension->type] = $suspension;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ush->update($user->userID, 'chatSuspensions', serialize($suspensions));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $suspensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the appropriate suspension for user, room and type.
|
||||||
|
* Returns false if no active suspension was found.
|
||||||
|
*
|
||||||
|
* @param \wcf\data\user\User $user
|
||||||
|
* @param \chat\data\room\Room $room
|
||||||
|
* @param integer $type
|
||||||
|
* @return \chat\data\suspension\Suspension
|
||||||
|
*/
|
||||||
|
public static function getSuspensionByUserRoomAndType(\wcf\data\user\User $user, \chat\data\room\Room $room, $type) {
|
||||||
|
$condition = new \wcf\system\database\util\PreparedStatementConditionBuilder();
|
||||||
|
$condition->add('userID = ?', array($user->userID));
|
||||||
|
$condition->add('type = ?', array($type));
|
||||||
|
$condition->add('expires > ?', array(TIME_NOW));
|
||||||
|
if ($room->roomID) $condition->add('roomID = ?', array($room->roomID));
|
||||||
|
else $condition->add('roomID IS NULL');
|
||||||
|
|
||||||
|
$sql = "SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
chat".WCF_N."_suspension
|
||||||
|
".$condition;
|
||||||
|
|
||||||
|
$statement = WCF::getDB()->prepareStatement($sql);
|
||||||
|
$statement->execute($condition->getParameters());
|
||||||
|
$row = $statement->fetchArray();
|
||||||
|
if (!$row) return false;
|
||||||
|
|
||||||
|
return new self(null, $row);
|
||||||
|
}
|
||||||
|
}
|
51
file/lib/data/suspension/SuspensionAction.class.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\data\suspension;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes chat-suspension-related actions.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage data.suspension
|
||||||
|
*/
|
||||||
|
class SuspensionAction extends \wcf\data\AbstractDatabaseObjectAction {
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\AbstractDatabaseObjectAction::$className
|
||||||
|
*/
|
||||||
|
protected $className = '\chat\data\suspension\SuspensionEditor';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\AbstractDatabaseObjectAction::$requireACP
|
||||||
|
*/
|
||||||
|
protected $requireACP = array('revoke');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates permissions and parameters
|
||||||
|
*/
|
||||||
|
public function validateRevoke() {
|
||||||
|
WCF::getSession()->checkPermissions((array) 'admin.chat.canManageSuspensions');
|
||||||
|
|
||||||
|
$this->parameters['revoker'] = WCF::getUser()->userID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Revokes suspensions.
|
||||||
|
*/
|
||||||
|
public function revoke() {
|
||||||
|
// TODO: ignore revokes if suspension already is revoked
|
||||||
|
if (!isset($this->parameters['revoker'])) {
|
||||||
|
$this->parameters['revoker'] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$objectAction = new self($this->objectIDs, 'update', array(
|
||||||
|
'data' => array(
|
||||||
|
'expires' => TIME_NOW,
|
||||||
|
'revoker' => $this->parameters['revoker']
|
||||||
|
)
|
||||||
|
));
|
||||||
|
$objectAction->executeAction();
|
||||||
|
}
|
||||||
|
}
|
28
file/lib/data/suspension/SuspensionEditor.class.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\data\suspension;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides functions to edit chat suspensions.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage data.chat.suspension
|
||||||
|
*/
|
||||||
|
class SuspensionEditor extends \wcf\data\DatabaseObjectEditor implements \wcf\data\IEditableCachedObject {
|
||||||
|
/**
|
||||||
|
* @see \wcf\data\DatabaseObjectDecorator::$baseClass
|
||||||
|
*/
|
||||||
|
protected static $baseClass = '\chat\data\suspension\Suspension';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the suspension cache.
|
||||||
|
*/
|
||||||
|
public static function resetCache() {
|
||||||
|
$ush = \wcf\system\user\storage\UserStorageHandler::getInstance();
|
||||||
|
|
||||||
|
$ush->resetAll('chatSuspensions');
|
||||||
|
}
|
||||||
|
}
|
18
file/lib/data/suspension/SuspensionList.class.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\data\suspension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a list of chat suspensions.
|
||||||
|
*
|
||||||
|
* @author Maximilian Mader
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage data.suspension
|
||||||
|
*/
|
||||||
|
class SuspensionList extends \wcf\data\DatabaseObjectList {
|
||||||
|
/**
|
||||||
|
* @see wcf\data\DatabaseObjectList::$className
|
||||||
|
*/
|
||||||
|
public $className = 'chat\data\suspension\Suspension';
|
||||||
|
}
|
230
file/lib/page/ChatPage.class.php
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\page;
|
||||||
|
use \chat\data;
|
||||||
|
use \wcf\system\exception;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the chat-interface
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage page
|
||||||
|
*/
|
||||||
|
class ChatPage extends \wcf\page\AbstractPage {
|
||||||
|
/**
|
||||||
|
* @see wcf\page\AbstractPage::$loginRequired
|
||||||
|
*/
|
||||||
|
public $loginRequired = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::$neededModules
|
||||||
|
*/
|
||||||
|
public $neededModules = array('MODULE_CHAT');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::$neededPermissions
|
||||||
|
*/
|
||||||
|
public $neededPermissions = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current room.
|
||||||
|
*
|
||||||
|
* @var \chat\data\room\Room
|
||||||
|
*/
|
||||||
|
public $room = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The given roomID.
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public $roomID = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of accessible rooms.
|
||||||
|
*
|
||||||
|
* @var \chat\data\room\RoomList
|
||||||
|
*/
|
||||||
|
public $rooms = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of installed commands.
|
||||||
|
*
|
||||||
|
* @var array<string>
|
||||||
|
*/
|
||||||
|
public $commands = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of smilies in the default category.
|
||||||
|
*
|
||||||
|
* @var array<\wcf\data\smiley\Smiley>
|
||||||
|
* @see \wcf\data\smiley\SmileyCache
|
||||||
|
*/
|
||||||
|
public $defaultSmilies = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of all smiley categories.
|
||||||
|
*
|
||||||
|
* @var array<\wcf\data\smiley\SmileyCategory>
|
||||||
|
* @see \wcf\data\smiley\SmileyCache
|
||||||
|
*/
|
||||||
|
public $smileyCategories = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* attachment handler
|
||||||
|
* @see \wcf\system\attachment\AttachmentHandler
|
||||||
|
*/
|
||||||
|
public $attachmentHandler = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see wcf\page\AbstractPage::$enableTracking
|
||||||
|
*/
|
||||||
|
public $enableTracking = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\IPage::assignVariables()
|
||||||
|
*/
|
||||||
|
public function assignVariables() {
|
||||||
|
parent::assignVariables();
|
||||||
|
|
||||||
|
$reflection = new \ReflectionClass('\chat\data\message\Message');
|
||||||
|
|
||||||
|
WCF::getTPL()->assign(array(
|
||||||
|
'room' => $this->room,
|
||||||
|
'roomID' => $this->roomID,
|
||||||
|
'rooms' => $this->rooms,
|
||||||
|
'commands' => $this->commands,
|
||||||
|
'messageTypes' => $reflection->getConstants(),
|
||||||
|
'defaultSmilies' => $this->defaultSmilies,
|
||||||
|
'smileyCategories' => $this->smileyCategories,
|
||||||
|
'attachmentHandler' => $this->attachmentHandler,
|
||||||
|
'sidebarCollapsed' => \wcf\system\user\collapsible\content\UserCollapsibleContentHandler::getInstance()->isCollapsed('com.woltlab.wcf.collapsibleSidebar', 'be.bastelstu.chat.ChatPage'),
|
||||||
|
'sidebarName' => 'be.bastelstu.chat.ChatPage'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\IPage::readData()
|
||||||
|
*/
|
||||||
|
public function readData() {
|
||||||
|
parent::readData();
|
||||||
|
|
||||||
|
$this->readRoom();
|
||||||
|
$this->readCommands();
|
||||||
|
|
||||||
|
// get default smilies
|
||||||
|
if (MODULE_SMILEY) {
|
||||||
|
$this->smileyCategories = \wcf\data\smiley\SmileyCache::getInstance()->getCategories();
|
||||||
|
foreach ($this->smileyCategories as $index => $category) {
|
||||||
|
$category->loadSmilies();
|
||||||
|
|
||||||
|
// remove empty categories
|
||||||
|
if (!count($category) || $category->isDisabled) {
|
||||||
|
unset($this->smileyCategories[$index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$firstCategory = reset($this->smileyCategories);
|
||||||
|
if ($firstCategory) {
|
||||||
|
$this->defaultSmilies = \wcf\data\smiley\SmileyCache::getInstance()->getCategorySmilies($firstCategory->categoryID ?: null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MODULE_ATTACHMENT) {
|
||||||
|
$this->attachmentHandler = new \wcf\system\attachment\AttachmentHandler('be.bastelstu.chat.message', 0, \wcf\util\StringUtil::getRandomID(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\IPage::readParameters()
|
||||||
|
*/
|
||||||
|
public function readParameters() {
|
||||||
|
parent::readParameters();
|
||||||
|
|
||||||
|
if (isset($_REQUEST['id'])) $this->roomID = (int) $_REQUEST['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads installed commands.
|
||||||
|
*/
|
||||||
|
public function readCommands() {
|
||||||
|
$regex = new \wcf\system\Regex('Command.class.php$');
|
||||||
|
$directory = \wcf\util\DirectoryUtil::getInstance(CHAT_DIR.'lib/system/command/commands/', false);
|
||||||
|
$files = $directory->getFiles(SORT_ASC, $regex);
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$command = $regex->replace(basename($file), '');
|
||||||
|
if ($command == 'Plain') continue;
|
||||||
|
$this->commands[] = mb_strtolower($command);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->commands = array_merge($this->commands, array_keys(\chat\system\command\CommandHandler::getAliasMap()));
|
||||||
|
sort($this->commands);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads room data.
|
||||||
|
*/
|
||||||
|
public function readRoom() {
|
||||||
|
$this->rooms = data\room\RoomCache::getInstance()->getRooms();
|
||||||
|
|
||||||
|
if ($this->roomID === 0) {
|
||||||
|
// no room given
|
||||||
|
if (CHAT_FORCE_ROOM_SELECT) {
|
||||||
|
$this->rooms = array_filter($this->rooms, function ($room) {
|
||||||
|
return $room->canEnter();
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$room = reset($this->rooms);
|
||||||
|
if ($room === null) {
|
||||||
|
// no valid room found
|
||||||
|
throw new exception\IllegalLinkException();
|
||||||
|
}
|
||||||
|
// redirect to first chat-room
|
||||||
|
\wcf\util\HeaderUtil::redirect(\wcf\system\request\LinkHandler::getInstance()->getLink('Chat', array(
|
||||||
|
'application' => 'chat',
|
||||||
|
'object' => $room
|
||||||
|
)));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($this->rooms[$this->roomID])) throw new exception\IllegalLinkException();
|
||||||
|
$this->room = $this->rooms[$this->roomID];
|
||||||
|
if (!$this->room->canEnter()) throw new exception\PermissionDeniedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\IPage::show()
|
||||||
|
*/
|
||||||
|
public function show() {
|
||||||
|
\wcf\system\menu\page\PageMenu::getInstance()->setActiveMenuItem('chat.header.menu.chat');
|
||||||
|
|
||||||
|
// remove index breadcrumb
|
||||||
|
WCF::getBreadcrumbs()->remove(0);
|
||||||
|
|
||||||
|
parent::show();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see wcf\page\ITrackablePage::getObjectType()
|
||||||
|
*/
|
||||||
|
public function getObjectType() {
|
||||||
|
return 'be.bastelstu.chat.room';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see wcf\page\ITrackablePage::getObjectID()
|
||||||
|
*/
|
||||||
|
public function getObjectID() {
|
||||||
|
if ($this->room === null) return 0;
|
||||||
|
|
||||||
|
return $this->room->roomID;
|
||||||
|
}
|
||||||
|
}
|
91
file/lib/page/CopyrightPage.class.php
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\page;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows information about Tims chat.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage page
|
||||||
|
*/
|
||||||
|
class CopyrightPage extends \wcf\page\AbstractPage {
|
||||||
|
/**
|
||||||
|
* @see wcf\page\AbstractPage::$loginRequired
|
||||||
|
*/
|
||||||
|
public $loginRequired = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::$neededModules
|
||||||
|
*/
|
||||||
|
public $neededModules = array('MODULE_CHAT');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::$neededPermissions
|
||||||
|
*/
|
||||||
|
public $neededPermissions = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::$templateName
|
||||||
|
*/
|
||||||
|
public $templateName = '__copyright';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\IPage::assignVariables()
|
||||||
|
*/
|
||||||
|
public function assignVariables() {
|
||||||
|
parent::assignVariables();
|
||||||
|
|
||||||
|
$images = explode("\n\n", file_get_contents(__FILE__, null, null, __COMPILER_HALT_OFFSET__ + 2));
|
||||||
|
|
||||||
|
\wcf\system\WCF::getTPL()->assign(array(
|
||||||
|
'background' => str_replace("\n", '', $images[array_rand($images)])
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// @codingStandardsIgnoreStart
|
||||||
|
__halt_compiler();/*iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAYAAADnRuK4AAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A
|
||||||
|
/wD/oL2nkwAAAAlwSFlzAAAOwgAADsIBFShKgAAAAAd0SU1FB9wBEhQiMYMbjeYAAARlSURBVHja
|
||||||
|
7d2/i5RHHMfxfS6b+AO54qocYrBQPAMxXSBF2hRiYWEl6QzBSmyMleBhFUNyxBQGNRDwR6O1iK1d
|
||||||
|
bNRAPNAiEJazSXMY7gy661+Qm4EdZ+eZeX3q4WaeZ97P+zs7O7dPN+hnFgd1Zq1vA54biABIACQA
|
||||||
|
EgCJAEgAJACSFtJl7i/JBuBkMkkymJ3LV4uajI3z36T6U9k2JId9pH48Hnv0C0kvAUplIGEgARAD
|
||||||
|
AQhAAFLChIEEQAzULkDBTcL19fWiDNRt31GlWbuui9mwXSsNIKWnQbMO3SAAMRCAGEgAxEAAAhCA
|
||||||
|
lDAAMVCb6eP9iT2RGNyYGo1GRV3Y7guXw432HSpqzB88ehBs8+LScpK+FhYWYpoFNxuH1T49hcER
|
||||||
|
k/f2fdK7MpcMIOubNtdJ9RoIQAASJUwAxEAAYiAAMdA7yPMnZY3nw496d597CdCBlevhRhH7QJPL
|
||||||
|
F4qajO6H2+FrP/djsM3T5dNK2LRw1GrN0jYbmy5hta7beglQHyej1k+ODAQgAAEIQEoYgBioRYBy
|
||||||
|
Xle9BorYJJxMjvRuzDGbjTnnohtEnDbccf5KeDL+fhZss/n+tjSjjtgHennycJV22fXL3WCb7U8f
|
||||||
|
hiF7tRls89+Nn/MZaG5/xObecFu2G93yl7sxc9FtbpRVwqxv2gyABEAAAhCAAAQgAAFIZgXQ+FnE
|
||||||
|
JljMPlCisz6O2PYMoI1rF5P8nZhTeQxUo4EKe+IB1DOASpswADEQgBgIQAACkLRYwnyMZyAGqgWg
|
||||||
|
N8//yPfEx5zKi/mvUwBNPacxiTqRmOolKakyf+VesM1fxz6rcuL33vk92Gbn61fBNv+e/SoMRxf+
|
||||||
|
Cc0oAzkwX19SVYxhzs4AVN/9YSAGYiAAMVCxTxiAGEhmXcKsgRgIQC3ZJeJ06Hh8tN0SFrNRdvCn
|
||||||
|
m8E2f546XtR1fXzpVvja9x4Itnmxco6BpoYs4kaXdl0xYy5tvqpdRLdc5or7fSA32oMBIA+GEgYg
|
||||||
|
BgIQAwHIdTGQ68oJ0KHvrgbbPP726yQD+vTitWCbbs/+JH19vvJbURMf8x6MXpawmAlLNehUcOSc
|
||||||
|
MAZSDiyiZw2Q8zcMxEAAYiDxrgxRwoSBZjTo4RdfImCLvH5wv6iHOevLVmKy+ev3KMkwF4/OnAi2
|
||||||
|
WVpaymegnBuAMv1cZD3SKhbaAJJ3s2Z1KxkIQMJAwkACoP9pZHOvmKSai/H4nzRbBpHtFvv2ZMT8
|
||||||
|
vl+tfSXMWu9KWM7vcWrtK6sRa63NLffVNEAMBCBWYCAAAUgJU8IYSF8AYgUGGkRsKA0SvbSFgaa/
|
||||||
|
h/Pz86nmtCwDtfxOMSWsQo0rYQzEQAzEQABiIAZiIAZiIAYCEIAAVITGR6NRtvHk7IuBBEAWksJA
|
||||||
|
AiBRwgRADAQgBhIGklmky9xf8NTi6uqqWdkiMb9bOEh02rA4A7GUEgYgKRsgC20AMRCAGEgYSAAk
|
||||||
|
AFLCqk5X4JgWTcuWWStpMHPmQwAkABIACYBEACQAEgBJE3kLMDdR/zhAlCMAAAAASUVORK5CYII=
|
||||||
|
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAAJYAAACWCAYAAAFLBkF0AAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A
|
||||||
|
/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9oMEgkcFcTqZcUAAAQDSURBVHja
|
||||||
|
7d3ddas6GIRh4uUm6MP9V5A+1Ma+OTkr8cKWkIT197x3sWMQw2j4JAu8bb3yFXl/f/o75Gxs37Zt
|
||||||
|
+/7+/vPi4/F4u9Gjje3PG3nm1UbvCR/4w7sdfR216vF4vPzQ7/f+2+H/rbvFDuenha9a+ptbTWvc
|
||||||
|
3735+1BjJ+Vly350e6fXaWs8b/Dg9ZB1mCXdaY98Llx+Nm+Jew8pHf1jLcNKsR2SI6g0tvff8ROL
|
||||||
|
7aPW3RIO50989xXbqbnWTWyHrMNcI7ZDakcX232n9plET7LiFQ3bz3S0g5gItRu25/T4SEPDsO6/
|
||||||
|
Fx55lFyloxn7fCU4u6Ojz8WqlSzFjpQ7uoyVejK7YUc7Lm1MVsPOntLcU18cF7FOEPn/heLiCj9V
|
||||||
|
vSRlcOqSdMvcQch8bfyCTKUIzDwAKRp83EZWaj9zXXxRZYSplaoyPEut5btWqstGXTpezD3tQxl9
|
||||||
|
rzH+i4wlwxpGP5owT51EFwldjglrjRPHVepoPiqlSlgiPKNVwruuH/l/VUKfkTC1UtkDhwzGHjhM
|
||||||
|
Y/TwdErDwWkOJafd6dOoJRoFANlVVU1KKrTQUizRTqwxumG0i5UMHxMnDQNnTeCsvZZralH6XR9n
|
||||||
|
NRzRX5EzWXzayZxFrPYBH11UcdTlruwqqfsrXe7OWT0GfEU3NC9NOKtnZ6W6o4cCl7OINWA3TAnq
|
||||||
|
mrMOKnizDnXGigXbN+ugdHA1VDoI+JqB3whfWKwS8CHBfSHRpaGlkzmLWMQiFrGIBQAAgBOMtA4+
|
||||||
|
tBZLUUosYhFr5YC/7A6LE99k+8JCNySWzErKp07v3QmcpRsSi1grculahytvn2txQeEsYhGLWDNW
|
||||||
|
8EnV+qfvgEi5za7munjOIhax5i5Ka+ZMDzManEUsYhFLwBfOFPR6mx1nEYtYxFo24K+sxHuo6jmL
|
||||||
|
WMRqzsfXOuR+PZaaT9Y66IbEIhYuKEprBjVn6YbEArHaVfBJVX0D3GGhGxKLWPhABV/ziWup2+Is
|
||||||
|
3ZBYxAKxiEUsYhGLWCAWsQAAAAAAQGu+FjjGFkugwurGMpUFxgJjgbGAtYr3KkV3i5vPKj/wd8iB
|
||||||
|
gMQCY4GxwFjAPMX7ZT+5NhuJA4HuCnyJBcYCY4GxgPrcR2781T9pdyWzD04kFhgLjIXFafIkxFrP
|
||||||
|
PB+5TkmtDys+H/6jk6gSC4wFxgJjAfW5z36ADYpkKzMkFhgLjAVMX2PVrHfUThILjAXGAhgLivfM
|
||||||
|
QrnXFRCzr8yQWGAsMBbAWGjD9M9uaHGLWM3C3LMbAMYCY4GxgB8sm4HEAmOBsYD6TP/LFBPglykA
|
||||||
|
xgJjgbGAbdvGnyBNKWz3wbclsQDGAmOBsQDGAmOBsQDGAmOBscBYJABjgbEAAAAAAAPwD1TbcSbk
|
||||||
|
TnGiAAAAAElFTkSuQmCC
|
161
file/lib/page/NewMessagesPage.class.php
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\page;
|
||||||
|
use \chat\data;
|
||||||
|
use \wcf\system\exception\IllegalLinkException;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads new messages.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage page
|
||||||
|
*/
|
||||||
|
class NewMessagesPage extends \wcf\page\AbstractPage {
|
||||||
|
/**
|
||||||
|
* @see wcf\page\AbstractPage::$loginRequired
|
||||||
|
*/
|
||||||
|
public $loginRequired = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The new and unseen messages.
|
||||||
|
*
|
||||||
|
* @var array<\wcf\data\chat\message\ChatMessage>
|
||||||
|
*/
|
||||||
|
public $messages = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::$neededModules
|
||||||
|
*/
|
||||||
|
public $neededModules = array('MODULE_CHAT');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::$neededPermissions
|
||||||
|
*/
|
||||||
|
public $neededPermissions = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The room the user joined.
|
||||||
|
*
|
||||||
|
* @var \chat\data\room\Room
|
||||||
|
*/
|
||||||
|
public $room = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All the users that are currently in the room $this->room.
|
||||||
|
*
|
||||||
|
* @var array<\wcf\data\user\UserProfile>
|
||||||
|
*/
|
||||||
|
public $users = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::$useTemplate
|
||||||
|
*/
|
||||||
|
public $useTemplate = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\Page::readData()
|
||||||
|
*/
|
||||||
|
public function readData() {
|
||||||
|
parent::readData();
|
||||||
|
|
||||||
|
$this->readRoom();
|
||||||
|
$this->readMessages();
|
||||||
|
$this->users = $this->room->getUsers();
|
||||||
|
|
||||||
|
$roomAction = new data\room\RoomAction(array(), 'removeDeadUsers');
|
||||||
|
$roomAction->executeAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the new messages
|
||||||
|
*/
|
||||||
|
public function readMessages() {
|
||||||
|
$this->messages = data\message\ViewableMessageList::getMessagesSince($this->room, WCF::getUser()->chatLastSeen);
|
||||||
|
|
||||||
|
// update last seen message
|
||||||
|
$sql = "SELECT
|
||||||
|
MAX(messageID)
|
||||||
|
FROM
|
||||||
|
chat".WCF_N."_message";
|
||||||
|
$stmt = WCF::getDB()->prepareStatement($sql);
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
$editor = new \wcf\data\user\UserEditor(WCF::getUser());
|
||||||
|
$editor->update(array(
|
||||||
|
'chatLastSeen' => $stmt->fetchColumn(),
|
||||||
|
'chatLastActivity' => TIME_NOW
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the room databaseobject.
|
||||||
|
*/
|
||||||
|
public function readRoom() {
|
||||||
|
$this->room = \chat\data\room\RoomCache::getInstance()->getRoom(WCF::getUser()->chatRoomID);
|
||||||
|
if (!$this->room) throw new IllegalLinkException();
|
||||||
|
if (!$this->room->canEnter()) throw new \wcf\system\exception\PermissionDeniedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\IPage::show()
|
||||||
|
*/
|
||||||
|
public function show() {
|
||||||
|
parent::show();
|
||||||
|
|
||||||
|
@header('Content-type: application/json');
|
||||||
|
\wcf\util\HeaderUtil::sendNoCacheHeaders();
|
||||||
|
|
||||||
|
$json = array('users' => array(), 'messages' => array());
|
||||||
|
|
||||||
|
foreach ($this->messages as $message) {
|
||||||
|
$json['messages'][] = $message->jsonify(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
\wcf\system\user\storage\UserStorageHandler::getInstance()->loadStorage(array_keys($this->users));
|
||||||
|
|
||||||
|
foreach ($this->users as $user) {
|
||||||
|
$json['users'][] = array(
|
||||||
|
'userID' => (int) $user->userID,
|
||||||
|
'username' => $user->username,
|
||||||
|
'awayStatus' => $user->chatAway,
|
||||||
|
'suspended' => (boolean) !$this->room->canWrite($user->getDecoratedObject()),
|
||||||
|
'avatar' => array(
|
||||||
|
16 => $user->getAvatar()->getImageTag(16),
|
||||||
|
24 => $user->getAvatar()->getImageTag(24),
|
||||||
|
32 => $user->getAvatar()->getImageTag(32),
|
||||||
|
48 => $user->getAvatar()->getImageTag(48)
|
||||||
|
),
|
||||||
|
'link' => \wcf\system\request\LinkHandler::getInstance()->getLink('User', array(
|
||||||
|
'object' => $user->getDecoratedObject()
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ENABLE_BENCHMARK) {
|
||||||
|
$b = \wcf\system\benchmark\Benchmark::getInstance();
|
||||||
|
$items = array();
|
||||||
|
if (ENABLE_DEBUG_MODE) {
|
||||||
|
foreach ($b->getItems() as $item) {
|
||||||
|
$items[] = array(
|
||||||
|
'text' => $item['text'],
|
||||||
|
'use' => $item['use'],
|
||||||
|
'trace' => $item['trace']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$json['benchmark'] = array(
|
||||||
|
'time' => $b->getExecutionTime(),
|
||||||
|
'queryTime' => $b->getQueryExecutionTime(),
|
||||||
|
'queryPercent' => $b->getQueryExecutionTime() / $b->getExecutionTime(),
|
||||||
|
'items' => $items
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo \wcf\util\JSON::encode($json);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
23
file/lib/system/CHATCore.class.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chat core
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system
|
||||||
|
*/
|
||||||
|
class CHATCore extends \wcf\system\application\AbstractApplication {
|
||||||
|
/**
|
||||||
|
* @see wcf\system\application\AbstractApplication::$abbreviation
|
||||||
|
*/
|
||||||
|
protected $abbreviation = 'chat';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see wcf\system\application\AbstractApplication::$primaryController
|
||||||
|
*/
|
||||||
|
protected $primaryController = 'chat\\page\\ChatPage';
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\attachment;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attachment object type implementation for chat messages.
|
||||||
|
*
|
||||||
|
* @author Maximilian Mader
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.attachment
|
||||||
|
*/
|
||||||
|
class MessageAttachmentObjectType extends \wcf\system\attachment\AbstractAttachmentObjectType {
|
||||||
|
/**
|
||||||
|
* @see wcf\system\attachment\IAttachmentObjectType::getMaxSize()
|
||||||
|
*/
|
||||||
|
public function getMaxSize() {
|
||||||
|
return WCF::getSession()->getPermission('user.chat.maxAttachmentSize');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see wcf\system\attachment\IAttachmentObjectType::getAllowedExtensions()
|
||||||
|
*/
|
||||||
|
public function getAllowedExtensions() {
|
||||||
|
return \wcf\util\ArrayUtil::trim(explode("\n", WCF::getSession()->getPermission('user.chat.allowedAttachmentExtensions')));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see wcf\system\attachment\IAttachmentObjectType::getMaxCount()
|
||||||
|
*/
|
||||||
|
public function getMaxCount() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see wcf\system\attachment\IAttachmentObjectType::canDownload()
|
||||||
|
*/
|
||||||
|
public function canDownload($objectID) {
|
||||||
|
if ($objectID) {
|
||||||
|
$message = new \chat\data\message\Message($objectID);
|
||||||
|
if (isset($message->roomID) && $message->roomID) {
|
||||||
|
$room = \chat\data\room\RoomCache::getInstance()->getRoom($message->roomID);
|
||||||
|
if ($room && $room->canEnter()) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see wcf\system\attachment\IAttachmentObjectType::canUpload()
|
||||||
|
*/
|
||||||
|
public function canUpload($objectID, $parentObjectID = 0) {
|
||||||
|
if ($objectID) {
|
||||||
|
$room = \chat\data\room\RoomCache::getInstance()->getRoom($parentObjectID);
|
||||||
|
if (!$room || !$room->canWrite()) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return WCF::getSession()->getPermission('user.chat.canUploadAttachment');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see wcf\system\attachment\IAttachmentObjectType::canDelete()
|
||||||
|
*/
|
||||||
|
public function canDelete($objectID) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
41
file/lib/system/cache/builder/PermissionCacheBuilder.class.php
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\cache\builder;
|
||||||
|
use wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Caches the chat permissions for a combination of user groups.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus, Marcel Werk
|
||||||
|
* @copyright 2010-2014 WoltLab GmbH
|
||||||
|
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.cache.builder
|
||||||
|
*/
|
||||||
|
class PermissionCacheBuilder extends \wcf\system\cache\builder\AbstractCacheBuilder {
|
||||||
|
/**
|
||||||
|
* @see wcf\system\cache\AbstractCacheBuilder::rebuild()
|
||||||
|
*/
|
||||||
|
public function rebuild(array $parameters) {
|
||||||
|
$data = array();
|
||||||
|
|
||||||
|
if (!empty($parameters)) {
|
||||||
|
$conditionBuilder = new \wcf\system\database\util\PreparedStatementConditionBuilder();
|
||||||
|
$conditionBuilder->add('acl_option.objectTypeID = ?', array(\wcf\system\acl\ACLHandler::getInstance()->getObjectTypeID('be.bastelstu.chat.room')));
|
||||||
|
$conditionBuilder->add('option_to_group.optionID = acl_option.optionID');
|
||||||
|
$conditionBuilder->add('option_to_group.groupID IN (?)', array($parameters));
|
||||||
|
$sql = "SELECT option_to_group.groupID, option_to_group.objectID AS roomID, option_to_group.optionValue,
|
||||||
|
acl_option.optionName AS permission
|
||||||
|
FROM wcf".WCF_N."_acl_option acl_option,
|
||||||
|
wcf".WCF_N."_acl_option_to_group option_to_group
|
||||||
|
".$conditionBuilder;
|
||||||
|
$stmt = WCF::getDB()->prepareStatement($sql);
|
||||||
|
$stmt->execute($conditionBuilder->getParameters());
|
||||||
|
while ($row = $stmt->fetchArray()) {
|
||||||
|
if (!isset($data[$row['roomID']][$row['permission']])) $data[$row['roomID']][$row['permission']] = $row['optionValue'];
|
||||||
|
else $data[$row['roomID']][$row['permission']] = $row['optionValue'] || $data[$row['roomID']][$row['permission']];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
25
file/lib/system/cache/builder/RoomCacheBuilder.class.php
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\cache\builder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Caches all chat rooms.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.cache.builder
|
||||||
|
*/
|
||||||
|
class RoomCacheBuilder extends \wcf\system\cache\builder\AbstractCacheBuilder {
|
||||||
|
/**
|
||||||
|
* @see \wcf\system\cache\AbstractCacheBuilder::rebuild()
|
||||||
|
*/
|
||||||
|
public function rebuild(array $parameters) {
|
||||||
|
// get all chat rooms
|
||||||
|
$roomList = new \chat\data\room\RoomList();
|
||||||
|
$roomList->sqlOrderBy = "room.showOrder";
|
||||||
|
$roomList->readObjects();
|
||||||
|
|
||||||
|
return $roomList->getObjects();
|
||||||
|
}
|
||||||
|
}
|
69
file/lib/system/command/AbstractCommand.class.php
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command;
|
||||||
|
use \wcf\system\event\EventHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation for commands.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command
|
||||||
|
*/
|
||||||
|
abstract class AbstractCommand implements ICommand {
|
||||||
|
/**
|
||||||
|
* Instance of the CommandHandler
|
||||||
|
*
|
||||||
|
* @var \chat\system\command\CommandHandler
|
||||||
|
*/
|
||||||
|
public $commandHandler = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should HTML be enabled?
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
* @see \chat\system\command\ICommand::SETTING_OFF
|
||||||
|
* @see \chat\system\command\ICommand::SETTING_ON
|
||||||
|
*/
|
||||||
|
public $enableHTML = ICommand::SETTING_OFF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should smilies be enabled?
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
* @see \chat\system\command\ICommand::SETTING_OFF
|
||||||
|
* @see \chat\system\command\ICommand::SETTING_ON
|
||||||
|
* @see \chat\system\command\ICommand::SETTING_USER
|
||||||
|
*/
|
||||||
|
public $enableSmilies = ICommand::SETTING_OFF;
|
||||||
|
|
||||||
|
public function __construct(CommandHandler $commandHandler) {
|
||||||
|
EventHandler::getInstance()->fireAction($this, 'shouldInit');
|
||||||
|
$this->commandHandler = $commandHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fires the didInit-event.
|
||||||
|
* You should call this when everything is properly inserted.
|
||||||
|
*/
|
||||||
|
public function didInit() {
|
||||||
|
EventHandler::getInstance()->fireAction($this, 'didInit');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default-Receiver: Everyone
|
||||||
|
*
|
||||||
|
* @see \chat\system\command\ICommand::getReceiver()
|
||||||
|
*/
|
||||||
|
public function getReceiver() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No additionaldata by default.
|
||||||
|
*/
|
||||||
|
public function getAdditionalData() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
29
file/lib/system/command/AbstractRestrictedCommand.class.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command;
|
||||||
|
use \wcf\system\event\EventHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation for restricted commands
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command
|
||||||
|
*/
|
||||||
|
abstract class AbstractRestrictedCommand extends AbstractCommand implements IRestrictedCommand {
|
||||||
|
public function __construct(CommandHandler $commandHandler) {
|
||||||
|
parent::__construct($commandHandler);
|
||||||
|
|
||||||
|
$this->checkPermission();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fires checkPermission event.
|
||||||
|
*
|
||||||
|
* @see \chat\system\command\IRestrictedCommand
|
||||||
|
*/
|
||||||
|
public function checkPermission() {
|
||||||
|
EventHandler::getInstance()->fireAction($this, 'checkPermission');
|
||||||
|
}
|
||||||
|
}
|
126
file/lib/system/command/AbstractSuspensionCommand.class.php
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command;
|
||||||
|
use \chat\data\suspension;
|
||||||
|
use \chat\util\ChatUtil;
|
||||||
|
use \wcf\data\user\User;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation for suspension commands
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command
|
||||||
|
*/
|
||||||
|
abstract class AbstractSuspensionCommand extends AbstractRestrictedCommand {
|
||||||
|
public $user = null;
|
||||||
|
public $expires = 0;
|
||||||
|
public $suspensionAction = null;
|
||||||
|
public $link = '';
|
||||||
|
public $room = null;
|
||||||
|
public $reason = '';
|
||||||
|
|
||||||
|
public function __construct(\chat\system\command\CommandHandler $commandHandler) {
|
||||||
|
parent::__construct($commandHandler);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$parameters = explode(',', $commandHandler->getParameters(), 3);
|
||||||
|
list($username, $modifier) = $parameters;
|
||||||
|
|
||||||
|
if (isset($parameters[2])) {
|
||||||
|
$this->reason = \wcf\util\StringUtil::trim($parameters[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$modifier = ChatUtil::timeModifier(\wcf\util\StringUtil::trim($modifier));
|
||||||
|
$expires = strtotime($modifier, TIME_NOW);
|
||||||
|
$this->expires = min(max(-0x80000000, $expires), 0x7FFFFFFF);
|
||||||
|
}
|
||||||
|
catch (\wcf\system\exception\SystemException $e) {
|
||||||
|
throw new \InvalidArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->user = User::getUserByUsername($username);
|
||||||
|
if (!$this->user->userID) throw new \chat\system\command\UserNotFoundException($username);
|
||||||
|
|
||||||
|
$profile = \wcf\system\request\LinkHandler::getInstance()->getLink('User', array(
|
||||||
|
'object' => $this->user
|
||||||
|
));
|
||||||
|
$this->link = "[url='".$profile."']".$this->user->username.'[/url]';
|
||||||
|
|
||||||
|
$this->executeAction();
|
||||||
|
|
||||||
|
$this->didInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function executeAction() {
|
||||||
|
if (static::IS_GLOBAL) $room = new \chat\data\room\Room(null, array('roomID' => null));
|
||||||
|
else $room = $this->room;
|
||||||
|
|
||||||
|
if ($suspension = suspension\Suspension::getSuspensionByUserRoomAndType($this->user, $room, static::SUSPENSION_TYPE)) {
|
||||||
|
if ($suspension->expires >= $this->expires) {
|
||||||
|
throw new \wcf\system\exception\UserInputException('text', WCF::getLanguage()->get('chat.suspension.exists'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$action = new suspension\SuspensionAction(array($suspension), 'revoke', array(
|
||||||
|
'revoker' => WCF::getUser()->userID
|
||||||
|
));
|
||||||
|
$action->executeAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->suspensionAction = new suspension\SuspensionAction(array(), 'create', array(
|
||||||
|
'data' => array(
|
||||||
|
'userID' => $this->user->userID,
|
||||||
|
'roomID' => $room->roomID ?: null,
|
||||||
|
'type' => static::SUSPENSION_TYPE,
|
||||||
|
'expires' => $this->expires,
|
||||||
|
'time' => TIME_NOW,
|
||||||
|
'issuer' => WCF::getUser()->userID,
|
||||||
|
'reason' => $this->reason
|
||||||
|
)
|
||||||
|
));
|
||||||
|
$this->suspensionAction->executeAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\IRestrictedChatCommand::checkPermission()
|
||||||
|
*/
|
||||||
|
public function checkPermission() {
|
||||||
|
parent::checkPermission();
|
||||||
|
|
||||||
|
$this->room = $this->commandHandler->getRoom();
|
||||||
|
if (WCF::getSession()->getPermission('admin.chat.canManageSuspensions')) return;
|
||||||
|
|
||||||
|
$ph = new \chat\system\permission\PermissionHandler();
|
||||||
|
if (static::IS_GLOBAL) {
|
||||||
|
WCF::getSession()->checkPermissions(array('mod.chat.canG'.static::SUSPENSION_TYPE));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!WCF::getSession()->getPermission('mod.chat.canG'.static::SUSPENSION_TYPE)) {
|
||||||
|
if (!$ph->getPermission($this->room, 'mod.can'.ucfirst(static::SUSPENSION_TYPE))) {
|
||||||
|
throw new \wcf\system\exception\PermissionDeniedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getType()
|
||||||
|
*/
|
||||||
|
public function getType() {
|
||||||
|
return \chat\data\message\Message::TYPE_MODERATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getMessage()
|
||||||
|
*/
|
||||||
|
public function getMessage() {
|
||||||
|
return serialize(array(
|
||||||
|
'link' => $this->link,
|
||||||
|
'expires' => $this->expires,
|
||||||
|
'type' => (static::IS_GLOBAL ? 'g' : '').static::SUSPENSION_TYPE,
|
||||||
|
'reason' => $this->reason
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command;
|
||||||
|
use \chat\data\suspension;
|
||||||
|
use \chat\util\ChatUtil;
|
||||||
|
use \wcf\data\user\User;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation for suspension commands
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command
|
||||||
|
*/
|
||||||
|
abstract class AbstractUnsuspensionCommand extends AbstractRestrictedCommand {
|
||||||
|
public $user = null;
|
||||||
|
public $suspensionAction = null;
|
||||||
|
public $link = '';
|
||||||
|
public $room = null;
|
||||||
|
|
||||||
|
public function __construct(\chat\system\command\CommandHandler $commandHandler) {
|
||||||
|
parent::__construct($commandHandler);
|
||||||
|
|
||||||
|
$username = rtrim($commandHandler->getParameters(), ',');
|
||||||
|
$this->user = User::getUserByUsername($username);
|
||||||
|
if (!$this->user->userID) throw new \chat\system\command\UserNotFoundException($username);
|
||||||
|
|
||||||
|
$profile = \wcf\system\request\LinkHandler::getInstance()->getLink('User', array(
|
||||||
|
'object' => $this->user
|
||||||
|
));
|
||||||
|
$this->link = "[url='".$profile."']".$this->user->username.'[/url]';
|
||||||
|
|
||||||
|
$this->executeAction();
|
||||||
|
|
||||||
|
$this->didInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function executeAction() {
|
||||||
|
if (static::IS_GLOBAL) $room = new \chat\data\room\Room(null, array('roomID' => null));
|
||||||
|
else $room = $this->room;
|
||||||
|
|
||||||
|
if ($suspension = suspension\Suspension::getSuspensionByUserRoomAndType($this->user, $room, static::SUSPENSION_TYPE)) {
|
||||||
|
$action = new suspension\SuspensionAction(array($suspension), 'revoke', array(
|
||||||
|
'revoker' => WCF::getUser()->userID
|
||||||
|
));
|
||||||
|
$action->executeAction();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new \wcf\system\exception\UserInputException('text', WCF::getLanguage()->get('chat.suspension.notExists'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\IRestrictedChatCommand::checkPermission()
|
||||||
|
*/
|
||||||
|
public function checkPermission() {
|
||||||
|
parent::checkPermission();
|
||||||
|
|
||||||
|
$this->room = $this->commandHandler->getRoom();
|
||||||
|
if (WCF::getSession()->getPermission('admin.chat.canManageSuspensions')) return;
|
||||||
|
|
||||||
|
$ph = new \chat\system\permission\PermissionHandler();
|
||||||
|
if (static::IS_GLOBAL) {
|
||||||
|
WCF::getSession()->checkPermissions(array('mod.chat.canG'.static::SUSPENSION_TYPE));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!WCF::getSession()->getPermission('mod.chat.canG'.static::SUSPENSION_TYPE)) {
|
||||||
|
if (!$ph->getPermission($this->room, 'mod.can'.ucfirst(static::SUSPENSION_TYPE))) {
|
||||||
|
throw new \wcf\system\exception\PermissionDeniedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getType()
|
||||||
|
*/
|
||||||
|
public function getType() {
|
||||||
|
return \chat\data\message\Message::TYPE_MODERATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getMessage()
|
||||||
|
*/
|
||||||
|
public function getMessage() {
|
||||||
|
return serialize(array(
|
||||||
|
'link' => $this->link,
|
||||||
|
'type' => 'un'.(static::IS_GLOBAL ? 'g' : '').static::SUSPENSION_TYPE,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
126
file/lib/system/command/CommandHandler.class.php
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command;
|
||||||
|
use \wcf\util\StringUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles commands
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command
|
||||||
|
*/
|
||||||
|
final class CommandHandler {
|
||||||
|
/**
|
||||||
|
* char that indicates a command
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const COMMAND_CHAR = '/';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message text
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $text = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* current room
|
||||||
|
* @var \chat\data\room\Room
|
||||||
|
*/
|
||||||
|
private $room = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialises the CommandHandler
|
||||||
|
*
|
||||||
|
* @param string $text
|
||||||
|
* @param \chat\data\room\Room $room
|
||||||
|
*/
|
||||||
|
public function __construct($text, \chat\data\room\Room $room = null) {
|
||||||
|
$this->text = $text;
|
||||||
|
$this->room = $room;
|
||||||
|
|
||||||
|
$aliases = self::getAliasMap();
|
||||||
|
foreach ($aliases as $search => $replace) {
|
||||||
|
$this->text = \wcf\system\Regex::compile('^'.preg_quote(self::COMMAND_CHAR.$search).'( |$)')->replace($this->text, self::COMMAND_CHAR.$replace.' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->text = \wcf\system\Regex::compile('^//')->replace($this->text, '/plain ');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the alias map. Key is the alias, value is the target.
|
||||||
|
*
|
||||||
|
* @return array<string>
|
||||||
|
*/
|
||||||
|
public static function getAliasMap() {
|
||||||
|
if (StringUtil::trim(CHAT_COMMAND_ALIASES) === '') return array();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = array();
|
||||||
|
foreach (explode("\n", StringUtil::unifyNewlines(StringUtil::toLowerCase(CHAT_COMMAND_ALIASES))) as $line) {
|
||||||
|
list($key, $val) = explode(':', $line, 2);
|
||||||
|
|
||||||
|
$result[StringUtil::trim($key)] = StringUtil::trim($val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
catch (\wcf\system\exception\SystemException $e) {
|
||||||
|
throw new \wcf\system\exception\SystemException("Invalid alias specified: '".$line."'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given text is a command.
|
||||||
|
*/
|
||||||
|
public function isCommand($text = null) {
|
||||||
|
if ($text === null) $text = $this->text;
|
||||||
|
|
||||||
|
return StringUtil::startsWith($text, static::COMMAND_CHAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the whole message.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getText() {
|
||||||
|
return $this->text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current room.
|
||||||
|
*
|
||||||
|
* @return \chat\data\room\Room
|
||||||
|
*/
|
||||||
|
public function getRoom() {
|
||||||
|
return $this->room;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the parameter-string.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getParameters() {
|
||||||
|
$parts = explode(' ', mb_substr($this->text, mb_strlen(static::COMMAND_CHAR)), 2);
|
||||||
|
|
||||||
|
if (!isset($parts[1])) return '';
|
||||||
|
return $parts[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the command.
|
||||||
|
*/
|
||||||
|
public function loadCommand() {
|
||||||
|
$parts = explode(' ', mb_substr($this->text, mb_strlen(static::COMMAND_CHAR)), 2);
|
||||||
|
|
||||||
|
$class = '\chat\system\command\commands\\'.ucfirst(strtolower($parts[0])).'Command';
|
||||||
|
if (!class_exists($class)) {
|
||||||
|
throw new NotFoundException($parts[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new $class($this);
|
||||||
|
}
|
||||||
|
}
|
54
file/lib/system/command/ICommand.class.php
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for chat-commands.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command
|
||||||
|
*/
|
||||||
|
interface ICommand {
|
||||||
|
/**
|
||||||
|
* Setting is forced to be disabled.
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
const SETTING_OFF = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setting is forced to be enabled.
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
const SETTING_ON = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user may decide whether this setting is on or off.
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
const SETTING_USER = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the message-type for this command.
|
||||||
|
*/
|
||||||
|
public function getType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the message-text for this command.
|
||||||
|
*/
|
||||||
|
public function getMessage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns additionalData to be saved within database
|
||||||
|
*/
|
||||||
|
public function getAdditionalData();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the receiver for this command.
|
||||||
|
*/
|
||||||
|
public function getReceiver();
|
||||||
|
}
|
20
file/lib/system/command/IRestrictedCommand.class.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for Restricted commands.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command
|
||||||
|
*/
|
||||||
|
interface IRestrictedCommand {
|
||||||
|
/**
|
||||||
|
* Checks the permission to use this command. Has to throw
|
||||||
|
* \wcf\system\exception\PermissionDeniedException when the
|
||||||
|
* user is not allowed to use the command.
|
||||||
|
*/
|
||||||
|
public function checkPermission();
|
||||||
|
}
|
32
file/lib/system/command/NotFoundException.class.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when a command is not found.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command
|
||||||
|
*/
|
||||||
|
class NotFoundException extends \Exception {
|
||||||
|
/**
|
||||||
|
* given command
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $command = '';
|
||||||
|
|
||||||
|
public function __construct($command) {
|
||||||
|
$this->command = $command;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the given command
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getCommand() {
|
||||||
|
return $this->command;
|
||||||
|
}
|
||||||
|
}
|
32
file/lib/system/command/UserNotFoundException.class.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when a user is not found.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command
|
||||||
|
*/
|
||||||
|
class UserNotFoundException extends \Exception {
|
||||||
|
/**
|
||||||
|
* given username
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $username = '';
|
||||||
|
|
||||||
|
public function __construct($username) {
|
||||||
|
$this->username = $username;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the given username
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getUsername() {
|
||||||
|
return $this->username;
|
||||||
|
}
|
||||||
|
}
|
38
file/lib/system/command/commands/AwayCommand.class.php
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command\commands;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks the user as away.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command.commands
|
||||||
|
*/
|
||||||
|
class AwayCommand extends \chat\system\command\AbstractCommand {
|
||||||
|
public function __construct(\chat\system\command\CommandHandler $commandHandler) {
|
||||||
|
parent::__construct($commandHandler);
|
||||||
|
|
||||||
|
$editor = new \wcf\data\user\UserEditor(WCF::getUser());
|
||||||
|
$editor->update(array(
|
||||||
|
'chatAway' => $commandHandler->getParameters()
|
||||||
|
));
|
||||||
|
$this->didInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getType()
|
||||||
|
*/
|
||||||
|
public function getType() {
|
||||||
|
return \chat\data\message\Message::TYPE_AWAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getMessage()
|
||||||
|
*/
|
||||||
|
public function getMessage() {
|
||||||
|
return \wcf\system\bbcode\PreParser::getInstance()->parse($this->commandHandler->getParameters(), explode(',', WCF::getSession()->getPermission('user.chat.allowedBBCodes')));
|
||||||
|
}
|
||||||
|
}
|
16
file/lib/system/command/commands/BanCommand.class.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command\commands;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bans a user.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command.commands
|
||||||
|
*/
|
||||||
|
class BanCommand extends \chat\system\command\AbstractSuspensionCommand {
|
||||||
|
const IS_GLOBAL = false;
|
||||||
|
const SUSPENSION_TYPE = \chat\data\suspension\Suspension::TYPE_BAN;
|
||||||
|
}
|
223
file/lib/system/command/commands/ColorCommand.class.php
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command\commands;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the color of the username
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command.commands
|
||||||
|
*/
|
||||||
|
class ColorCommand extends \chat\system\command\AbstractCommand {
|
||||||
|
/**
|
||||||
|
* Map names to hexcodes
|
||||||
|
*
|
||||||
|
* @var array<integer>
|
||||||
|
*/
|
||||||
|
public static $colors = array(
|
||||||
|
'aliceblue' => 0xF0F8FF,
|
||||||
|
'antiquewhite' => 0xFAEBD7,
|
||||||
|
'aqua' => 0x00FFFF,
|
||||||
|
'aquamarine' => 0x7FFFD4,
|
||||||
|
'azure' => 0xF0FFFF,
|
||||||
|
'beige' => 0xF5F5DC,
|
||||||
|
'bisque' => 0xFFE4C4,
|
||||||
|
'black' => 0x000000,
|
||||||
|
'blanchedalmond' => 0xFFEBCD,
|
||||||
|
'blue' => 0x0000FF,
|
||||||
|
'bluescreenblue' => 0x0000AA,
|
||||||
|
'blueviolet' => 0x8A2BE2,
|
||||||
|
'brown' => 0xA52A2A,
|
||||||
|
'burlywood' => 0xDEB887,
|
||||||
|
'cadetblue' => 0x5F9EA0,
|
||||||
|
'chartreuse' => 0x7FFF00,
|
||||||
|
'chocolate' => 0xD2691E,
|
||||||
|
'coral' => 0xFF7F50,
|
||||||
|
'cornflowerblue' => 0x6495ED,
|
||||||
|
'cornsilk' => 0xFFF8DC,
|
||||||
|
'crimson' => 0xDC143C,
|
||||||
|
'cyan' => 0x00FFFF,
|
||||||
|
'darkblue' => 0x00008B,
|
||||||
|
'darkcyan' => 0x008B8B,
|
||||||
|
'darkgoldenrod' => 0xB8860B,
|
||||||
|
'darkgray' => 0xA9A9A9,
|
||||||
|
'darkgrey' => 0xA9A9A9,
|
||||||
|
'darkgreen' => 0x006400,
|
||||||
|
'darkkhaki' => 0xBDB76B,
|
||||||
|
'darkmagenta' => 0x8B008B,
|
||||||
|
'darkolivegreen' => 0x556B2F,
|
||||||
|
'darkorange' => 0xFF8C00,
|
||||||
|
'darkorchid' => 0x9932CC,
|
||||||
|
'darkred' => 0x8B0000,
|
||||||
|
'darksalmon' => 0xE9967A,
|
||||||
|
'darkseagreen' => 0x8FBC8F,
|
||||||
|
'darkslateblue' => 0x483D8B,
|
||||||
|
'darkslategray' => 0x2F4F4F,
|
||||||
|
'darkslategrey' => 0x2F4F4F,
|
||||||
|
'darkturquoise' => 0x00CED1,
|
||||||
|
'darkviolet' => 0x9400D3,
|
||||||
|
'deeppink' => 0xFF1493,
|
||||||
|
'deepskyblue' => 0x00BFFF,
|
||||||
|
'dimgray' => 0x696969,
|
||||||
|
'dimgrey' => 0x696969,
|
||||||
|
'dodgerblue' => 0x1E90FF,
|
||||||
|
'firebrick' => 0xB22222,
|
||||||
|
'floralwhite' => 0xFFFAF0,
|
||||||
|
'forestgreen' => 0x228B22,
|
||||||
|
'fuchsia' => 0xFF00FF,
|
||||||
|
'gainsboro' => 0xDCDCDC,
|
||||||
|
'ghostwhite' => 0xF8F8FF,
|
||||||
|
'gold' => 0xFFD700,
|
||||||
|
'goldenrod' => 0xDAA520,
|
||||||
|
'gray' => 0x808080,
|
||||||
|
'grey' => 0x808080,
|
||||||
|
'green' => 0x008000,
|
||||||
|
'greenyellow' => 0xADFF2F,
|
||||||
|
'honeydew' => 0xF0FFF0,
|
||||||
|
'hotpink' => 0xFF69B4,
|
||||||
|
'indianred' => 0xCD5C5C,
|
||||||
|
'indigo' => 0x4B0082,
|
||||||
|
'ivory' => 0xFFFFF0,
|
||||||
|
'khaki' => 0xF0E68C,
|
||||||
|
'lavender' => 0xE6E6FA,
|
||||||
|
'lavenderblush' => 0xFFF0F5,
|
||||||
|
'lawngreen' => 0x7CFC00,
|
||||||
|
'lemonchiffon' => 0xFFFACD,
|
||||||
|
'lightblue' => 0xADD8E6,
|
||||||
|
'lightcoral' => 0xF08080,
|
||||||
|
'lightcyan' => 0xE0FFFF,
|
||||||
|
'lightgoldenrodyellow' => 0xFAFAD2,
|
||||||
|
'lightgray' => 0xD3D3D3,
|
||||||
|
'lightgrey' => 0xD3D3D3,
|
||||||
|
'lightgreen' => 0x90EE90,
|
||||||
|
'lightpink' => 0xFFB6C1,
|
||||||
|
'lightsalmon' => 0xFFA07A,
|
||||||
|
'lightseagreen' => 0x20B2AA,
|
||||||
|
'lightskyblue' => 0x87CEFA,
|
||||||
|
'lightslategray' => 0x778899,
|
||||||
|
'lightslategrey' => 0x778899,
|
||||||
|
'lightsteelblue' => 0xB0C4DE,
|
||||||
|
'lightyellow' => 0xFFFFE0,
|
||||||
|
'lime' => 0x00FF00,
|
||||||
|
'limegreen' => 0x32CD32,
|
||||||
|
'linen' => 0xFAF0E6,
|
||||||
|
'magenta' => 0xFF00FF,
|
||||||
|
'maroon' => 0x800000,
|
||||||
|
'mediumaquamarine' => 0x66CDAA,
|
||||||
|
'mediumblue' => 0x0000CD,
|
||||||
|
'mediumorchid' => 0xBA55D3,
|
||||||
|
'mediumpurple' => 0x9370D8,
|
||||||
|
'mediumseagreen' => 0x3CB371,
|
||||||
|
'mediumslateblue' => 0x7B68EE,
|
||||||
|
'mediumspringgreen' => 0x00FA9A,
|
||||||
|
'mediumturquoise' => 0x48D1CC,
|
||||||
|
'mediumvioletred' => 0xC71585,
|
||||||
|
'midnightblue' => 0x191970,
|
||||||
|
'mintcream' => 0xF5FFFA,
|
||||||
|
'mistyrose' => 0xFFE4E1,
|
||||||
|
'moccasin' => 0xFFE4B5,
|
||||||
|
'navajowhite' => 0xFFDEAD,
|
||||||
|
'navy' => 0x000080,
|
||||||
|
'oldlace' => 0xFDF5E6,
|
||||||
|
'olive' => 0x808000,
|
||||||
|
'olivedrab' => 0x6B8E23,
|
||||||
|
'orange' => 0xFFA500,
|
||||||
|
'orangered' => 0xFF4500,
|
||||||
|
'orchid' => 0xDA70D6,
|
||||||
|
'oxford' => 0xF02D, // looks like green
|
||||||
|
'palegoldenrod' => 0xEEE8AA,
|
||||||
|
'palegreen' => 0x98FB98,
|
||||||
|
'paleturquoise' => 0xAFEEEE,
|
||||||
|
'palevioletred' => 0xD87093,
|
||||||
|
'papayawhip' => 0xFFEFD5,
|
||||||
|
'peachpuff' => 0xFFDAB9,
|
||||||
|
'peru' => 0xCD853F,
|
||||||
|
'pink' => 0xFFC0CB,
|
||||||
|
'plum' => 0xDDA0DD,
|
||||||
|
'powderblue' => 0xB0E0E6,
|
||||||
|
'purple' => 0x800080,
|
||||||
|
'red' => 0xFF0000,
|
||||||
|
'rosybrown' => 0xBC8F8F,
|
||||||
|
'royalblue' => 0x4169E1,
|
||||||
|
'saddlebrown' => 0x8B4513,
|
||||||
|
'sadwin' => 0x2067B2,
|
||||||
|
'salmon' => 0xFA8072,
|
||||||
|
'sandybrown' => 0xF4A460,
|
||||||
|
'seagreen' => 0x2E8B57,
|
||||||
|
'seashell' => 0xFFF5EE,
|
||||||
|
'sienna' => 0xA0522D,
|
||||||
|
'silver' => 0xC0C0C0,
|
||||||
|
'skyblue' => 0x87CEEB,
|
||||||
|
'slateblue' => 0x6A5ACD,
|
||||||
|
'slategray' => 0x708090,
|
||||||
|
'slategrey' => 0x708090,
|
||||||
|
'snow' => 0xFFFAFA,
|
||||||
|
'springgreen' => 0x00FF7F,
|
||||||
|
'steelblue' => 0x4682B4,
|
||||||
|
'tan' => 0xD2B48C,
|
||||||
|
'teal' => 0x008080,
|
||||||
|
'thistle' => 0xD8BFD8,
|
||||||
|
'tomato' => 0xFF6347,
|
||||||
|
'turquoise' => 0x40E0D0,
|
||||||
|
'violet' => 0xEE82EE,
|
||||||
|
'wheat' => 0xF5DEB3,
|
||||||
|
'white' => 0xFFFFFF,
|
||||||
|
'whitesmoke' => 0xF5F5F5,
|
||||||
|
'yellow' => 0xFFFF00,
|
||||||
|
'yellowgreen' => 0x9ACD32
|
||||||
|
);
|
||||||
|
|
||||||
|
public function __construct(\chat\system\command\CommandHandler $commandHandler) {
|
||||||
|
parent::__construct($commandHandler);
|
||||||
|
|
||||||
|
try {
|
||||||
|
list($color[1], $color[2]) = explode(' ', $commandHandler->getParameters(), 2);
|
||||||
|
}
|
||||||
|
catch (\wcf\system\exception\SystemException $e) {
|
||||||
|
$color[1] = $color[2] = $commandHandler->getParameters();
|
||||||
|
}
|
||||||
|
|
||||||
|
$regex = new \wcf\system\Regex('^#?([a-f0-9]{3}|[a-f0-9]{6})$', \wcf\system\Regex::CASE_INSENSITIVE);
|
||||||
|
foreach ($color as $key => $val) {
|
||||||
|
if (isset(self::$colors[$val])) $color[$key] = self::$colors[$val];
|
||||||
|
else {
|
||||||
|
if (!$regex->match($val)) throw new \InvalidArgumentException();
|
||||||
|
|
||||||
|
$matches = $regex->getMatches();
|
||||||
|
$val = $matches[1];
|
||||||
|
if (strlen($val) == 3) $val = $val[0].$val[0].$val[1].$val[1].$val[2].$val[2];
|
||||||
|
$color[$key] = hexdec($val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$editor = new \wcf\data\user\UserEditor(\wcf\system\WCF::getUser());
|
||||||
|
$editor->update(array(
|
||||||
|
'chatColor1' => $color[1],
|
||||||
|
'chatColor2' => $color[2]
|
||||||
|
));
|
||||||
|
$this->didInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getType()
|
||||||
|
*/
|
||||||
|
public function getType() {
|
||||||
|
return \chat\data\message\Message::TYPE_INFORMATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getMessage()
|
||||||
|
*/
|
||||||
|
public function getMessage() {
|
||||||
|
return \wcf\system\WCF::getLanguage()->get('chat.message.color.success');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getReceiver()
|
||||||
|
*/
|
||||||
|
public function getReceiver() {
|
||||||
|
return \wcf\system\WCF::getUser()->userID;
|
||||||
|
}
|
||||||
|
}
|
30
file/lib/system/command/commands/FreeCommand.class.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command\commands;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Informs everyone that the fish was freed. OH A NOEZ.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command.commands
|
||||||
|
*/
|
||||||
|
class FreeCommand extends MeCommand {
|
||||||
|
public function __construct(\chat\system\command\CommandHandler $commandHandler) {
|
||||||
|
parent::__construct($commandHandler);
|
||||||
|
|
||||||
|
if (mb_strtolower($this->commandHandler->getParameters()) != 'the fish') {
|
||||||
|
throw new \InvalidArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->didInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getMessage()
|
||||||
|
*/
|
||||||
|
public function getMessage() {
|
||||||
|
return 'freed the fish. OH A NOEZ';
|
||||||
|
}
|
||||||
|
}
|
16
file/lib/system/command/commands/GbanCommand.class.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command\commands;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Globally bans a user.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command.commands
|
||||||
|
*/
|
||||||
|
class GbanCommand extends \chat\system\command\AbstractSuspensionCommand {
|
||||||
|
const IS_GLOBAL = true;
|
||||||
|
const SUSPENSION_TYPE = \chat\data\suspension\Suspension::TYPE_BAN;
|
||||||
|
}
|
16
file/lib/system/command/commands/GmuteCommand.class.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command\commands;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Globally mutes a user.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command.commands
|
||||||
|
*/
|
||||||
|
class GmuteCommand extends \chat\system\command\AbstractSuspensionCommand {
|
||||||
|
const IS_GLOBAL = true;
|
||||||
|
const SUSPENSION_TYPE = \chat\data\suspension\Suspension::TYPE_MUTE;
|
||||||
|
}
|
116
file/lib/system/command/commands/InfoCommand.class.php
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command\commands;
|
||||||
|
use \chat\util\ChatUtil;
|
||||||
|
use \wcf\data\user\User;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
use \wcf\util\DateUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows information about the specified user.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command.commands
|
||||||
|
*/
|
||||||
|
class InfoCommand extends \chat\system\command\AbstractCommand {
|
||||||
|
public $lines = array();
|
||||||
|
public $user = null;
|
||||||
|
|
||||||
|
public function __construct(\chat\system\command\CommandHandler $commandHandler) {
|
||||||
|
parent::__construct($commandHandler);
|
||||||
|
|
||||||
|
$username = rtrim($commandHandler->getParameters(), ',');
|
||||||
|
$this->user = User::getUserByUsername($username);
|
||||||
|
if (!$this->user->userID) throw new \chat\system\command\UserNotFoundException($username);
|
||||||
|
|
||||||
|
// Username + link to profile
|
||||||
|
$profile = \wcf\system\request\LinkHandler::getInstance()->getLink('User', array(
|
||||||
|
'object' => $this->user
|
||||||
|
));
|
||||||
|
$this->lines[WCF::getLanguage()->get('wcf.user.username')] = "[url='".$profile."']".$this->user->username.'[/url]';
|
||||||
|
|
||||||
|
// Away-Status
|
||||||
|
if ($this->user->chatAway !== null) {
|
||||||
|
$this->lines[WCF::getLanguage()->get('wcf.chat.away')] = $this->user->chatAway;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Room
|
||||||
|
$room = \chat\data\room\RoomCache::getInstance()->getRoom($this->user->chatRoomID);
|
||||||
|
if ($room !== null && $room->canEnter()) {
|
||||||
|
$this->lines[WCF::getLanguage()->get('chat.global.room')] = $room->getTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Suspensions
|
||||||
|
$suspensions = \chat\data\suspension\Suspension::getSuspensionsForUser($this->user);
|
||||||
|
foreach ($suspensions as $roomSuspensions) {
|
||||||
|
foreach ($roomSuspensions as $typeSuspension) {
|
||||||
|
if (!$typeSuspension->isValid()) continue;
|
||||||
|
if (!$typeSuspension->isVisible()) continue;
|
||||||
|
|
||||||
|
$dateTime = DateUtil::getDateTimeByTimestamp($typeSuspension->expires);
|
||||||
|
$name = WCF::getLanguage()->getDynamicVariable('chat.global.information.suspension', array(
|
||||||
|
'suspension' => $typeSuspension,
|
||||||
|
'room' => \chat\data\room\RoomCache::getInstance()->getRoom($typeSuspension->roomID)
|
||||||
|
));
|
||||||
|
$this->lines[$name] = str_replace('%time%', DateUtil::format($dateTime, DateUtil::TIME_FORMAT), str_replace('%date%', DateUtil::format($dateTime, DateUtil::DATE_FORMAT), WCF::getLanguage()->get('wcf.date.dateTimeFormat')));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ip address
|
||||||
|
if (WCF::getSession()->getPermission('admin.user.canViewIpAddress')) {
|
||||||
|
$session = $this->fetchSession();
|
||||||
|
if ($session) {
|
||||||
|
$this->lines[WCF::getLanguage()->get('wcf.user.ipAddress')] = \wcf\util\UserUtil::convertIPv6To4($session->ipAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->didInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the sessiondatabase object for the specified user.
|
||||||
|
*
|
||||||
|
* @return \wcf\data\session\Session
|
||||||
|
*/
|
||||||
|
public function fetchSession() {
|
||||||
|
$sql = "SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
wcf".WCF_N."_session
|
||||||
|
WHERE
|
||||||
|
userID = ?";
|
||||||
|
$stmt = WCF::getDB()->prepareStatement($sql);
|
||||||
|
$stmt->execute(array($this->user->userID));
|
||||||
|
$row = $stmt->fetchArray();
|
||||||
|
if (!$row) return false;
|
||||||
|
|
||||||
|
return new \wcf\data\session\Session(null, $row);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getType()
|
||||||
|
*/
|
||||||
|
public function getType() {
|
||||||
|
return \chat\data\message\Message::TYPE_INFORMATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getMessage()
|
||||||
|
*/
|
||||||
|
public function getMessage() {
|
||||||
|
$lines = array();
|
||||||
|
foreach ($this->lines as $key => $val) {
|
||||||
|
$lines[] = '[b]'.$key.':[/b] '.$val;
|
||||||
|
}
|
||||||
|
return '[list][*]'.implode('[*]', $lines).'[/list]';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getReceiver()
|
||||||
|
*/
|
||||||
|
public function getReceiver() {
|
||||||
|
return \wcf\system\WCF::getUser()->userID;
|
||||||
|
}
|
||||||
|
}
|
76
file/lib/system/command/commands/InviteCommand.class.php
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command\commands;
|
||||||
|
use \wcf\data\user\User;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invites a user into a temproom.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command.commands
|
||||||
|
*/
|
||||||
|
class InviteCommand extends \chat\system\command\AbstractRestrictedCommand {
|
||||||
|
public $user = null;
|
||||||
|
public $link = '';
|
||||||
|
public $room = null;
|
||||||
|
|
||||||
|
public function __construct(\chat\system\command\CommandHandler $commandHandler) {
|
||||||
|
parent::__construct($commandHandler);
|
||||||
|
|
||||||
|
$username = rtrim($commandHandler->getParameters(), ',');
|
||||||
|
$this->user = User::getUserByUsername($username);
|
||||||
|
if (!$this->user->userID) throw new \chat\system\command\UserNotFoundException($username);
|
||||||
|
|
||||||
|
$acl = \wcf\system\acl\ACLHandler::getInstance();
|
||||||
|
$permissions = $acl->getPermissions($acl->getObjectTypeID('be.bastelstu.chat.room'), array($this->room->roomID));
|
||||||
|
|
||||||
|
$newPermission = array();
|
||||||
|
foreach ($permissions['options'] as $option) {
|
||||||
|
$newPermission[$option->optionID] = ($option->categoryName == 'user') ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$_POST['aclValues'] = array(
|
||||||
|
'user' => $permissions['user'][$this->room->roomID],
|
||||||
|
'group' => $permissions['group'][$this->room->roomID]
|
||||||
|
);
|
||||||
|
$_POST['aclValues']['user'][$this->user->userID] = $newPermission;
|
||||||
|
|
||||||
|
$acl->save($this->room->roomID, $acl->getObjectTypeID('be.bastelstu.chat.room'));
|
||||||
|
\chat\system\permission\PermissionHandler::clearCache();
|
||||||
|
$this->didInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\IRestrictedChatCommand::checkPermission()
|
||||||
|
*/
|
||||||
|
public function checkPermission() {
|
||||||
|
parent::checkPermission();
|
||||||
|
|
||||||
|
$this->room = $this->commandHandler->getRoom();
|
||||||
|
if ($this->room->owner != WCF::getUser()->userID) throw new \wcf\system\exception\PermissionDeniedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getType()
|
||||||
|
*/
|
||||||
|
public function getType() {
|
||||||
|
return \chat\data\message\Message::TYPE_INFORMATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getMessage()
|
||||||
|
*/
|
||||||
|
public function getMessage() {
|
||||||
|
return \wcf\system\WCF::getLanguage()->getDynamicVariable('chat.message.invite.success', array('user' => $this->user, 'room' => $this->room));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getReceiver()
|
||||||
|
*/
|
||||||
|
public function getReceiver() {
|
||||||
|
return \wcf\system\WCF::getUser()->userID;
|
||||||
|
}
|
||||||
|
}
|
38
file/lib/system/command/commands/MeCommand.class.php
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command\commands;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates an action. The message is shown without the colon.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command.commands
|
||||||
|
*/
|
||||||
|
class MeCommand extends \chat\system\command\AbstractCommand {
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\AbstractCommand::$enableSmilies
|
||||||
|
*/
|
||||||
|
public $enableSmilies = self::SETTING_USER;
|
||||||
|
|
||||||
|
public function __construct(\chat\system\command\CommandHandler $commandHandler) {
|
||||||
|
parent::__construct($commandHandler);
|
||||||
|
|
||||||
|
$this->didInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getType()
|
||||||
|
*/
|
||||||
|
public function getType() {
|
||||||
|
return \chat\data\message\Message::TYPE_ME;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getMessage()
|
||||||
|
*/
|
||||||
|
public function getMessage() {
|
||||||
|
return $this->commandHandler->getParameters();
|
||||||
|
}
|
||||||
|
}
|
16
file/lib/system/command/commands/MuteCommand.class.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command\commands;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mutes a user.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command.commands
|
||||||
|
*/
|
||||||
|
class MuteCommand extends \chat\system\command\AbstractSuspensionCommand {
|
||||||
|
const IS_GLOBAL = false;
|
||||||
|
const SUSPENSION_TYPE = \chat\data\suspension\Suspension::TYPE_MUTE;
|
||||||
|
}
|
36
file/lib/system/command/commands/PlainCommand.class.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command\commands;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a message that starts with a slash.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command.commands
|
||||||
|
*/
|
||||||
|
class PlainCommand extends \chat\system\command\AbstractCommand {
|
||||||
|
public $enableSmilies = \chat\system\command\ICommand::SETTING_USER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getType()
|
||||||
|
*/
|
||||||
|
public function getType() {
|
||||||
|
return \chat\data\message\Message::TYPE_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getMessage()
|
||||||
|
*/
|
||||||
|
public function getMessage() {
|
||||||
|
return \wcf\system\bbcode\PreParser::getInstance()->parse(\chat\system\command\CommandHandler::COMMAND_CHAR.$this->commandHandler->getParameters(), explode(',', \wcf\system\WCF::getSession()->getPermission('user.chat.allowedBBCodes')));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getReceiver()
|
||||||
|
*/
|
||||||
|
public function getReceiver() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
66
file/lib/system/command/commands/RestoreCommand.class.php
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command\commands;
|
||||||
|
use \wcf\data\user\User;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
use \wcf\util\ChatUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the color of a user
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command.commands
|
||||||
|
*/
|
||||||
|
class RestoreCommand extends \chat\system\command\AbstractRestrictedCommand {
|
||||||
|
public $enableHTML = 1;
|
||||||
|
public $user = null;
|
||||||
|
public $link = '';
|
||||||
|
|
||||||
|
public function __construct(\chat\system\command\CommandHandler $commandHandler) {
|
||||||
|
parent::__construct($commandHandler);
|
||||||
|
|
||||||
|
$username = rtrim($commandHandler->getParameters(), ',');
|
||||||
|
$this->user = User::getUserByUsername($username);
|
||||||
|
if (!$this->user->userID) throw new \chat\system\command\UserNotFoundException($username);
|
||||||
|
|
||||||
|
$profile = \wcf\system\request\LinkHandler::getInstance()->getLink('User', array(
|
||||||
|
'object' => $this->user
|
||||||
|
));
|
||||||
|
$this->link = "[url='".$profile."']".$this->user->username.'[/url]';
|
||||||
|
|
||||||
|
$editor = new \wcf\data\user\UserEditor($this->user);
|
||||||
|
$editor->update(array(
|
||||||
|
'chatColor1' => 0,
|
||||||
|
'chatColor2' => 0
|
||||||
|
));
|
||||||
|
$this->didInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\IRestrictedChatCommand::checkPermission()
|
||||||
|
*/
|
||||||
|
public function checkPermission() {
|
||||||
|
parent::checkPermission();
|
||||||
|
|
||||||
|
WCF::getSession()->checkPermissions(array('mod.chat.canRestore'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getType()
|
||||||
|
*/
|
||||||
|
public function getType() {
|
||||||
|
return \chat\data\message\Message::TYPE_MODERATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getMessage()
|
||||||
|
*/
|
||||||
|
public function getMessage() {
|
||||||
|
return serialize(array(
|
||||||
|
'link' => $this->link,
|
||||||
|
'type' => str_replace(array('chat\system\command\commands\\', 'command'), '', strtolower(get_class($this)))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
97
file/lib/system/command/commands/TemproomCommand.class.php
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command\commands;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a temporary room
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command.commands
|
||||||
|
*/
|
||||||
|
class TemproomCommand extends \chat\system\command\AbstractRestrictedCommand {
|
||||||
|
public $roomName = '';
|
||||||
|
public $roomID = 0;
|
||||||
|
|
||||||
|
public function __construct(\chat\system\command\CommandHandler $commandHandler) {
|
||||||
|
parent::__construct($commandHandler);
|
||||||
|
|
||||||
|
// create room
|
||||||
|
$this->objectAction = new \chat\data\room\RoomAction(array(), 'create', array('data' => array(
|
||||||
|
'title' => 'Temproom',
|
||||||
|
'topic' => '',
|
||||||
|
'permanent' => 0,
|
||||||
|
'owner' => WCF::getUser()->userID
|
||||||
|
)));
|
||||||
|
$this->objectAction->executeAction();
|
||||||
|
$returnValues = $this->objectAction->getReturnValues();
|
||||||
|
$chatRoomEditor = new \chat\data\room\RoomEditor($returnValues['returnValues']);
|
||||||
|
$this->roomID = $returnValues['returnValues']->roomID;
|
||||||
|
$this->roomName = WCF::getLanguage()->getDynamicVariable('chat.room.titleTemp', array('roomID' => $this->roomID));
|
||||||
|
|
||||||
|
// set accurate title
|
||||||
|
$chatRoomEditor->update(array(
|
||||||
|
'title' => $this->roomName
|
||||||
|
));
|
||||||
|
|
||||||
|
// set permissions
|
||||||
|
$acl = \wcf\system\acl\ACLHandler::getInstance();
|
||||||
|
$options = $acl->getOptions($acl->getObjectTypeID('be.bastelstu.chat.room'))->getObjects();
|
||||||
|
$_POST['aclValues'] = array(
|
||||||
|
'user' => array(
|
||||||
|
// creators may do everything
|
||||||
|
WCF::getUser()->userID => array_fill_keys(array_keys($options), 1)
|
||||||
|
),
|
||||||
|
'group' => array(
|
||||||
|
// anyone else may do nothing
|
||||||
|
\wcf\data\user\group\UserGroup::EVERYONE => array_fill_keys(array_keys($options), 0)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$acl->save($this->roomID, $acl->getObjectTypeID('be.bastelstu.chat.room'));
|
||||||
|
\chat\system\permission\PermissionHandler::clearCache();
|
||||||
|
$this->didInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\IRestrictedCommand::checkPermission()
|
||||||
|
*/
|
||||||
|
public function checkPermission() {
|
||||||
|
parent::checkPermission();
|
||||||
|
|
||||||
|
WCF::getSession()->checkPermissions(array('user.chat.canTempRoom'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getType()
|
||||||
|
*/
|
||||||
|
public function getType() {
|
||||||
|
return \chat\data\message\Message::TYPE_INFORMATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getMessage()
|
||||||
|
*/
|
||||||
|
public function getMessage() {
|
||||||
|
return WCF::getLanguage()->getDynamicVariable('chat.message.temproom.success', array('roomName' => $this->roomName));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getReceiver()
|
||||||
|
*/
|
||||||
|
public function getReceiver() {
|
||||||
|
return \wcf\system\WCF::getUser()->userID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getAdditionalData()
|
||||||
|
*/
|
||||||
|
public function getAdditionalData() {
|
||||||
|
return array(
|
||||||
|
'roomID' => (int) $this->roomID,
|
||||||
|
'roomName' => $this->roomName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
16
file/lib/system/command/commands/UnbanCommand.class.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command\commands;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bans a user.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command.commands
|
||||||
|
*/
|
||||||
|
class UnbanCommand extends \chat\system\command\AbstractUnsuspensionCommand {
|
||||||
|
const IS_GLOBAL = false;
|
||||||
|
const SUSPENSION_TYPE = \chat\data\suspension\Suspension::TYPE_BAN;
|
||||||
|
}
|