upload
95
API.php
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/* · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· Q V I T T E R ·
|
||||||
|
· ·
|
||||||
|
· http://github.com/hannesmannerheim/qvitter ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· <o) ·
|
||||||
|
· /_//// ·
|
||||||
|
· (____/ ·
|
||||||
|
· (o< ·
|
||||||
|
· o> \\\\_\ ·
|
||||||
|
· \\) \____) ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· Qvitter is free software: you can redistribute it and / or modify it ·
|
||||||
|
· under the terms of the GNU Affero General Public License as published by ·
|
||||||
|
· the Free Software Foundation, either version three of the License or (at ·
|
||||||
|
· your option) any later version. ·
|
||||||
|
· ·
|
||||||
|
· Qvitter is distributed in hope that it will be useful but WITHOUT ANY ·
|
||||||
|
· WARRANTY; without even the implied warranty of MERCHANTABILTY or FITNESS ·
|
||||||
|
· FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for ·
|
||||||
|
· more details. ·
|
||||||
|
· ·
|
||||||
|
· You should have received a copy of the GNU Affero General Public License ·
|
||||||
|
· along with Qvitter. If not, see <http://www.gnu.org/licenses/>. ·
|
||||||
|
· ·
|
||||||
|
· Contact h@nnesmannerhe.im if you have any questions. ·
|
||||||
|
· ·
|
||||||
|
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
include 'settings.php';
|
||||||
|
|
||||||
|
header("Content-type: application/json; charset=utf-8");
|
||||||
|
if(substr($apiroot,-1) != '/') { $apiroot .= '/'; } // add slash if missing
|
||||||
|
|
||||||
|
// post requests
|
||||||
|
if(isset($_POST['postRequest'])) {
|
||||||
|
$query = http_build_query($_POST, '', '&');
|
||||||
|
$ch=curl_init();
|
||||||
|
curl_setopt($ch, CURLOPT_URL, $apiroot.urldecode($_POST['postRequest']));
|
||||||
|
curl_setopt($ch, CURLOPT_USERPWD, $_POST['username'].":".$_POST['password']);
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||||
|
curl_setopt($ch, CURLOPT_POST, 1);
|
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
|
||||||
|
session_write_close(); // fix problem with curling to local
|
||||||
|
$reply=curl_exec($ch);
|
||||||
|
curl_close($ch);
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
// force ssl on our domain
|
||||||
|
if($forcessl) {
|
||||||
|
$reply = str_replace('http://'.$siterootdomain,'https://'.$siterootdomain,$reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
print $reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get requests
|
||||||
|
elseif(isset($_POST['getRequest'])) {
|
||||||
|
$ch=curl_init();
|
||||||
|
curl_setopt($ch, CURLOPT_URL, $apiroot.$_POST['getRequest']);
|
||||||
|
|
||||||
|
if(isset($_POST['username'])) {
|
||||||
|
curl_setopt($ch, CURLOPT_USERPWD, $_POST['username'].":".$_POST['password']);
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||||
|
session_write_close();
|
||||||
|
$reply=curl_exec($ch);
|
||||||
|
curl_close($ch);
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
// force ssl on our domain
|
||||||
|
if($forcessl) {
|
||||||
|
$reply = str_replace('http:\/\/'.$siterootdomain,'https:\/\/'.$siterootdomain,$reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
print $reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
|
||||||
|
· ·
|
||||||
|
· (o> >o) ·
|
||||||
|
· \\\\_\ /_//// .
|
||||||
|
· \____) (____/ ·
|
||||||
|
· ·
|
||||||
|
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */?>
|
661
LICENSE
Executable file
|
@ -0,0 +1,661 @@
|
||||||
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 19 November 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU Affero General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works, specifically designed to ensure
|
||||||
|
cooperation with the community in the case of network server software.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
our General Public Licenses are intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
Developers that use our General Public Licenses protect your rights
|
||||||
|
with two steps: (1) assert copyright on the software, and (2) offer
|
||||||
|
you this License which gives you legal permission to copy, distribute
|
||||||
|
and/or modify the software.
|
||||||
|
|
||||||
|
A secondary benefit of defending all users' freedom is that
|
||||||
|
improvements made in alternate versions of the program, if they
|
||||||
|
receive widespread use, become available for other developers to
|
||||||
|
incorporate. Many developers of free software are heartened and
|
||||||
|
encouraged by the resulting cooperation. However, in the case of
|
||||||
|
software used on network servers, this result may fail to come about.
|
||||||
|
The GNU General Public License permits making a modified version and
|
||||||
|
letting the public access it on a server without ever releasing its
|
||||||
|
source code to the public.
|
||||||
|
|
||||||
|
The GNU Affero General Public License is designed specifically to
|
||||||
|
ensure that, in such cases, the modified source code becomes available
|
||||||
|
to the community. It requires the operator of a network server to
|
||||||
|
provide the source code of the modified version running there to the
|
||||||
|
users of that server. Therefore, public use of a modified version, on
|
||||||
|
a publicly accessible server, gives the public access to the source
|
||||||
|
code of the modified version.
|
||||||
|
|
||||||
|
An older license, called the Affero General Public License and
|
||||||
|
published by Affero, was designed to accomplish similar goals. This is
|
||||||
|
a different license, not a version of the Affero GPL, but Affero has
|
||||||
|
released a new version of the Affero GPL which permits relicensing under
|
||||||
|
this license.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, if you modify the
|
||||||
|
Program, your modified version must prominently offer all users
|
||||||
|
interacting with it remotely through a computer network (if your version
|
||||||
|
supports such interaction) an opportunity to receive the Corresponding
|
||||||
|
Source of your version by providing access to the Corresponding Source
|
||||||
|
from a network server at no charge, through some standard or customary
|
||||||
|
means of facilitating copying of software. This Corresponding Source
|
||||||
|
shall include the Corresponding Source for any work covered by version 3
|
||||||
|
of the GNU General Public License that is incorporated pursuant to the
|
||||||
|
following paragraph.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the work with which it is combined will remain governed by version
|
||||||
|
3 of the GNU General Public License.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU Affero General Public License from time to time. Such new versions
|
||||||
|
will be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU Affero General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU Affero General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU Affero General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If your software can interact with users remotely through a computer
|
||||||
|
network, you should also make sure that it provides a way for users to
|
||||||
|
get its source. For example, if your program is a web application, its
|
||||||
|
interface could display a "Source" link that leads users to an archive
|
||||||
|
of the code. There are many ways you could offer source, and different
|
||||||
|
solutions will be better for different programs; see section 13 for the
|
||||||
|
specific requirements.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
76
README.md
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
Qvitter
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
* Author: Hannes Mannerheim (<h@nnesmannerhe.im>)
|
||||||
|
* Last mod.: August, 2013
|
||||||
|
* Version: 1
|
||||||
|
* Website: <http://beaneditor.org/>
|
||||||
|
* GitHub: <https://github.com/hannesmannerheim/qvitter>
|
||||||
|
|
||||||
|
Qvitter is free software: you can redistribute it and / or modify it
|
||||||
|
under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version three of the License or (at
|
||||||
|
your option) any later version.
|
||||||
|
|
||||||
|
Qvitter is distributed in hope that it will be useful but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILTY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
||||||
|
more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Qvitter. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Setup
|
||||||
|
-----
|
||||||
|
|
||||||
|
You need a webserver with PHP support.
|
||||||
|
|
||||||
|
Edit settings.php.
|
||||||
|
|
||||||
|
(Qvitter uses a slightly modified statusnet API. Some things will not work
|
||||||
|
if you connect to a site with standard API. Files are included if you want
|
||||||
|
to Qvitter-mod your Statusnet API.)
|
||||||
|
|
||||||
|
|
||||||
|
TODO
|
||||||
|
----
|
||||||
|
|
||||||
|
1. Join new external groups and follow new external users
|
||||||
|
|
||||||
|
2. Follow people on other instances
|
||||||
|
|
||||||
|
3. Auto suggest mentions
|
||||||
|
|
||||||
|
4. Register
|
||||||
|
|
||||||
|
5. Background image uploading/editing
|
||||||
|
|
||||||
|
6. Color theme
|
||||||
|
|
||||||
|
7. Auto url-shortening setting under queet box
|
||||||
|
|
||||||
|
10. Settings (e.g. don't show replies to people I don't follow)
|
||||||
|
|
||||||
|
11. Syntax-coloring in queet-box, maybe codemirror (worked nicely for ltr but not rtl text when I tried it)
|
||||||
|
|
||||||
|
12. Image/file upload, drag-n-drop!
|
||||||
|
|
||||||
|
13. Search users
|
||||||
|
|
||||||
|
14. Recommended users
|
||||||
|
|
||||||
|
15. Filters (hide queets containing strings, e.g. mute users)
|
||||||
|
|
||||||
|
18. Better responsive design
|
||||||
|
|
||||||
|
19. More languages
|
||||||
|
|
||||||
|
20. Queet-page
|
||||||
|
|
||||||
|
21. New api for serving _number_ of new items in several streams (to show number of new items in menu/history)
|
||||||
|
|
||||||
|
22. New "expand queet" api for getting conversation, retweets, favs and attachment in the same request
|
||||||
|
|
||||||
|
23. DMs
|
||||||
|
|
||||||
|
24. Node.js long polling server and an new api that serve aggregate of all polling users requests in one go
|
160
api-changes-1.1.1/CHANGES
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
CHANGES TO API
|
||||||
|
--------------
|
||||||
|
|
||||||
|
* actions/apiattachment.php New api action
|
||||||
|
* actions/apistatusesfavs.php New api action
|
||||||
|
* actions/apicheckhub.php New api action (not used yet)
|
||||||
|
* actions/apiexternalprofileshow.php New api action
|
||||||
|
|
||||||
|
* lib/apiaction.php
|
||||||
|
|
||||||
|
- add urls to larger avatars
|
||||||
|
|
||||||
|
~LINE 213 $avatar = $profile->getAvatar(AVATAR_STREAM_SIZE);
|
||||||
|
$twitter_user['profile_image_url'] = ($avatar) ? $avatar->displayUrl() :
|
||||||
|
Avatar::defaultImage(AVATAR_STREAM_SIZE);
|
||||||
|
$avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
|
||||||
|
$twitter_user['profile_image_url_profile_size'] = ($avatar) ? $avatar->displayUrl() :
|
||||||
|
Avatar::defaultImage(AVATAR_PROFILE_SIZE);
|
||||||
|
$avatar = $profile->getOriginalAvatar();
|
||||||
|
$twitter_user['profile_image_url_original'] = ($avatar) ? $avatar->displayUrl() :
|
||||||
|
Avatar::defaultImage(AVATAR_PROFILE_SIZE);
|
||||||
|
$groups = $profile->getGroups();
|
||||||
|
$groups_count = 0; while($groups->fetch()) $groups_count++;
|
||||||
|
$twitter_user['groups_count'] = $groups_count;
|
||||||
|
|
||||||
|
|
||||||
|
- add the uri-field
|
||||||
|
|
||||||
|
~line 320 $twitter_status['uri'] = $notice->uri;
|
||||||
|
|
||||||
|
|
||||||
|
- show if a notices is favorited by auth_user
|
||||||
|
|
||||||
|
~line 345 if (isset($this->auth_user)) {
|
||||||
|
$this_profile = $this->auth_user->getProfile();
|
||||||
|
$twitter_status['favorited'] = $this->auth_user->hasFave($notice);
|
||||||
|
$twitter_status['repeated'] = $this_profile->hasRepeated($notice->id);
|
||||||
|
} else {
|
||||||
|
$twitter_status['favorited'] = false;
|
||||||
|
$twitter_status['repeated'] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- show number of admins in group api
|
||||||
|
|
||||||
|
~line 420 $admins = $group->getAdmins();
|
||||||
|
$admin_count = 0; while($admins->fetch()) $admin_count++;
|
||||||
|
$twitter_group['admin_count'] = $admin_count;
|
||||||
|
|
||||||
|
|
||||||
|
- to be able to get group profile by uri.
|
||||||
|
- hackish though, because if uri get-var is sent, it will discard the id get var
|
||||||
|
- (but id still needs to be sent and be non-numerical, so I do "?id=foo&uri={uri}")
|
||||||
|
- should be possible to only supply uri get var, but I was lazy... sry
|
||||||
|
|
||||||
|
~line 1565 } else if ($this->arg('uri')) {
|
||||||
|
return User_group::staticGet('uri', urldecode($this->arg('uri')));
|
||||||
|
|
||||||
|
|
||||||
|
* lib/router.php
|
||||||
|
|
||||||
|
- add routing for new api actions
|
||||||
|
|
||||||
|
~line 467: $m->connect('api/statuses/favs/:id.json',
|
||||||
|
array('action' => 'ApiStatusesFavs',
|
||||||
|
'id' => '[0-9]+'));
|
||||||
|
|
||||||
|
$m->connect('api/attachment/:id.json',
|
||||||
|
array('action' => 'ApiAttachment',
|
||||||
|
'id' => '[0-9]+'));
|
||||||
|
|
||||||
|
$m->connect('api/checkhub.json',
|
||||||
|
array('action' => 'ApiCheckHub'));
|
||||||
|
|
||||||
|
$m->connect('api/externalprofile/show.json',
|
||||||
|
array('action' => 'ApiExternalProfileShow'));
|
||||||
|
|
||||||
|
|
||||||
|
- also, tags need regexp to work with unicode charachters, e.g. farsi and arabic:
|
||||||
|
|
||||||
|
$m->connect('api/statusnet/tags/timeline/:tag.:format',
|
||||||
|
array('action' => 'ApiTimelineTag',
|
||||||
|
'tag' => self::REGEX_TAG,
|
||||||
|
'format' => '(xml|json|rss|atom|as)'));
|
||||||
|
|
||||||
|
|
||||||
|
* acitons/apiconversation.php
|
||||||
|
|
||||||
|
- I didn't always get Profile::current() to show me the auth user's profile, so I changed it to the normal $this->auth_user used in other api actions
|
||||||
|
|
||||||
|
~ line 80: if(isset($this->auth_user)) {
|
||||||
|
$profile = $this->auth_user->getProfile();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$profile = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*actions/apitimelineuser.php
|
||||||
|
|
||||||
|
- this api did only return the public user timeline, not the auth user's.
|
||||||
|
- e.g. it did not show notices from people who post to "my colleques at quitter"
|
||||||
|
- changed to return timeline according to which auth user is requesting
|
||||||
|
|
||||||
|
~ line 238 $user_profile = $this->user->getProfile();
|
||||||
|
if(isset($this->auth_user)) {
|
||||||
|
$auth_user_profile = $this->auth_user->getProfile();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$auth_user_profile = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stream = new ProfileNoticeStream($user_profile, $auth_user_profile);
|
||||||
|
|
||||||
|
$notice = $stream->getNotices(($this->page-1) * $this->count,
|
||||||
|
$this->count + 1,
|
||||||
|
$this->since_id,
|
||||||
|
$this->max_id);
|
||||||
|
|
||||||
|
|
||||||
|
* search.json
|
||||||
|
|
||||||
|
- changed response to normal twitter format, maybe I should have created a new api action for that,
|
||||||
|
- but... i don't see the point in having a special format for searches, it should be same as other streams
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
* actions/timelinetags.php
|
||||||
|
|
||||||
|
- added max_id and since_id
|
||||||
|
|
||||||
|
~line 179 $notice = Notice_tag::getStream(
|
||||||
|
$this->tag,
|
||||||
|
($this->page - 1) * $this->count,
|
||||||
|
$this->count + 1,
|
||||||
|
$this->since_id,
|
||||||
|
$this->max_id
|
||||||
|
);
|
||||||
|
|
||||||
|
* actions/apistatusesupdate.php
|
||||||
|
|
||||||
|
- we don't want statuses to shorten if sent through the api
|
||||||
|
|
||||||
|
~ line 290: //$status_shortened = $this->auth_user->shortenlinks($this->status);
|
||||||
|
$status_shortened = $this->status;
|
||||||
|
|
||||||
|
|
||||||
|
* classes/Notice.php
|
||||||
|
|
||||||
|
- to _not_ shorten urls sent through api, we need to comment out this also
|
||||||
|
|
||||||
|
~ line 352 // if ($user) {
|
||||||
|
// // Use the local user's shortening preferences, if applicable.
|
||||||
|
// $final = $user->shortenLinks($content);
|
||||||
|
// } else {
|
||||||
|
// $final = common_shorten_links($content);
|
||||||
|
// }
|
||||||
|
|
106
api-changes-1.1.1/actions/apiattachment.php
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StatusNet, the distributed open-source microblogging tool
|
||||||
|
*
|
||||||
|
* Show a notice's attachment
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* @category API
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Hannes Mannerheim <h@nnesmannerhe.im>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('STATUSNET')) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once INSTALLDIR . '/lib/apiauth.php';
|
||||||
|
require_once INSTALLDIR . '/lib/mediafile.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a notice's attachment
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class ApiAttachmentAction extends ApiAuthAction
|
||||||
|
{
|
||||||
|
const MAXCOUNT = 100;
|
||||||
|
|
||||||
|
var $original = null;
|
||||||
|
var $cnt = self::MAXCOUNT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take arguments for running
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST args
|
||||||
|
*
|
||||||
|
* @return boolean success flag
|
||||||
|
*/
|
||||||
|
function prepare($args)
|
||||||
|
{
|
||||||
|
parent::prepare($args);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the request
|
||||||
|
*
|
||||||
|
* Make a new notice for the update, save it, and show it
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST data (unused)
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function handle($args)
|
||||||
|
{
|
||||||
|
parent::handle($args);
|
||||||
|
$file = new File();
|
||||||
|
$file->selectAdd(); // clears it
|
||||||
|
$file->selectAdd('url');
|
||||||
|
$file->id = $this->trimmed('id');
|
||||||
|
$url = $file->fetchAll('url');
|
||||||
|
|
||||||
|
$file_txt = '';
|
||||||
|
if(strstr($url[0],'.html')) {
|
||||||
|
$file_txt['txt'] = file_get_contents(str_replace('://quitter.se','://127.0.0.1',$url[0]));
|
||||||
|
$file_txt['body_start'] = strpos($file_txt['txt'],'<body>')+6;
|
||||||
|
$file_txt['body_end'] = strpos($file_txt['txt'],'</body>');
|
||||||
|
$file_txt = substr($file_txt['txt'],$file_txt['body_start'],$file_txt['body_end']-$file_txt['body_start']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->initDocument('json');
|
||||||
|
$this->showJsonObjects($file_txt);
|
||||||
|
$this->endDocument('json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if read only.
|
||||||
|
*
|
||||||
|
* MAY override
|
||||||
|
*
|
||||||
|
* @param array $args other arguments
|
||||||
|
*
|
||||||
|
* @return boolean is read only action?
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
122
api-changes-1.1.1/actions/apicheckhub.php
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StatusNet, the distributed open-source microblogging tool
|
||||||
|
*
|
||||||
|
* Show a notice's attachment
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* @category API
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Hannes Mannerheim <h@nnesmannerhe.im>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('STATUSNET')) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once INSTALLDIR . '/lib/apiauth.php';
|
||||||
|
require_once INSTALLDIR . '/lib/mediafile.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a url have a push-hub, i.e. if it is possible to subscribe
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class ApiCheckHubAction extends ApiAuthAction
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Take arguments for running
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST args
|
||||||
|
*
|
||||||
|
* @return boolean success flag
|
||||||
|
*/
|
||||||
|
function prepare($args)
|
||||||
|
{
|
||||||
|
parent::prepare($args);
|
||||||
|
|
||||||
|
$this->url = urldecode($args['url']);
|
||||||
|
|
||||||
|
if (!$this->url) {
|
||||||
|
$this->clientError(_('No URL.'), 403, 'json');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Validate::uri(
|
||||||
|
$this->url, array(
|
||||||
|
'allowed_schemes' =>
|
||||||
|
array('http', 'https')
|
||||||
|
)
|
||||||
|
)) {
|
||||||
|
$this->clientError(_('Invalid URL.'), 403, 'json');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the request
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST data (unused)
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function handle($args)
|
||||||
|
{
|
||||||
|
|
||||||
|
$discover = new FeedDiscovery();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$feeduri = $discover->discoverFromURL($this->url);
|
||||||
|
if($feeduri) {
|
||||||
|
$huburi = $discover->getHubLink();
|
||||||
|
}
|
||||||
|
} catch (FeedSubNoFeedException $e) {
|
||||||
|
$this->clientError(_('No feed found'), 403, 'json');
|
||||||
|
return;
|
||||||
|
} catch (FeedSubBadResponseException $e) {
|
||||||
|
$this->clientError(_('No hub found'), 403, 'json');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$hub_status = array();
|
||||||
|
if ($huburi) {
|
||||||
|
$hub_status = array('huburi' => $huburi);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->initDocument('json');
|
||||||
|
$this->showJsonObjects($hub_status);
|
||||||
|
$this->endDocument('json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if read only.
|
||||||
|
*
|
||||||
|
* MAY override
|
||||||
|
*
|
||||||
|
* @param array $args other arguments
|
||||||
|
*
|
||||||
|
* @return boolean is read only action?
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
244
api-changes-1.1.1/actions/apiconversation.php
Normal file
|
@ -0,0 +1,244 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StatusNet - the distributed open-source microblogging tool
|
||||||
|
* Copyright (C) 2011, StatusNet, Inc.
|
||||||
|
*
|
||||||
|
* Show a stream of notices in a particular conversation
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* @category API
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @copyright 2011 StatusNet, Inc.
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('STATUSNET')) {
|
||||||
|
// This check helps protect against security problems;
|
||||||
|
// your code file can't be executed directly from the web.
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once INSTALLDIR . '/lib/apiauth.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a stream of notices in a particular conversation
|
||||||
|
*
|
||||||
|
* @category API
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @copyright 2011 StatusNet, Inc.
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
class ApiconversationAction extends ApiAuthAction
|
||||||
|
{
|
||||||
|
protected $conversation = null;
|
||||||
|
protected $notices = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For initializing members of the class.
|
||||||
|
*
|
||||||
|
* @param array $argarray misc. arguments
|
||||||
|
*
|
||||||
|
* @return boolean true
|
||||||
|
*/
|
||||||
|
function prepare($argarray)
|
||||||
|
{
|
||||||
|
parent::prepare($argarray);
|
||||||
|
|
||||||
|
$convId = $this->trimmed('id');
|
||||||
|
|
||||||
|
if (empty($convId)) {
|
||||||
|
// TRANS: Client exception thrown when no conversation ID is given.
|
||||||
|
throw new ClientException(_('No conversation ID.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->conversation = Conversation::staticGet('id', $convId);
|
||||||
|
|
||||||
|
if (empty($this->conversation)) {
|
||||||
|
// TRANS: Client exception thrown when referring to a non-existing conversation ID (%d).
|
||||||
|
throw new ClientException(sprintf(_('No conversation with ID %d.'), $convId),
|
||||||
|
404);
|
||||||
|
}
|
||||||
|
|
||||||
|
// $profile = Profile::current();
|
||||||
|
if(isset($this->auth_user)) {
|
||||||
|
$profile = $this->auth_user->getProfile();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$profile = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stream = new ConversationNoticeStream($convId, $profile);
|
||||||
|
|
||||||
|
$notice = $stream->getNotices(($this->page-1) * $this->count,
|
||||||
|
$this->count,
|
||||||
|
$this->since_id,
|
||||||
|
$this->max_id);
|
||||||
|
|
||||||
|
$this->notices = $notice->fetchAll();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler method
|
||||||
|
*
|
||||||
|
* @param array $argarray is ignored since it's now passed in in prepare()
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function handle($argarray=null)
|
||||||
|
{
|
||||||
|
$sitename = common_config('site', 'name');
|
||||||
|
// TRANS: Title for conversion timeline.
|
||||||
|
$title = _m('TITLE', 'Conversation');
|
||||||
|
$id = common_local_url('apiconversation', array('id' => $this->conversation->id, 'format' => $this->format));
|
||||||
|
$link = common_local_url('conversation', array('id' => $this->conversation->id));
|
||||||
|
|
||||||
|
$self = $id;
|
||||||
|
|
||||||
|
switch($this->format) {
|
||||||
|
case 'xml':
|
||||||
|
$this->showXmlTimeline($this->notices);
|
||||||
|
break;
|
||||||
|
case 'rss':
|
||||||
|
$this->showRssTimeline(
|
||||||
|
$this->notices,
|
||||||
|
$title,
|
||||||
|
$link,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
$self
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'atom':
|
||||||
|
|
||||||
|
header('Content-Type: application/atom+xml; charset=utf-8');
|
||||||
|
|
||||||
|
$atom = new AtomNoticeFeed($this->auth_user);
|
||||||
|
|
||||||
|
$atom->setId($id);
|
||||||
|
$atom->setTitle($title);
|
||||||
|
$atom->setUpdated('now');
|
||||||
|
|
||||||
|
$atom->addLink($link);
|
||||||
|
$atom->setSelfLink($self);
|
||||||
|
|
||||||
|
$atom->addEntryFromNotices($this->notices);
|
||||||
|
$this->raw($atom->getString());
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'json':
|
||||||
|
$this->showJsonTimeline($this->notices);
|
||||||
|
break;
|
||||||
|
case 'as':
|
||||||
|
header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE);
|
||||||
|
$doc = new ActivityStreamJSONDocument($this->auth_user);
|
||||||
|
$doc->setTitle($title);
|
||||||
|
$doc->addLink($link, 'alternate', 'text/html');
|
||||||
|
$doc->addItemsFromNotices($this->notices);
|
||||||
|
$this->raw($doc->asString());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// TRANS: Client error displayed when coming across a non-supported API method.
|
||||||
|
$this->clientError(_('API method not found.'), $code = 404);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if read only.
|
||||||
|
*
|
||||||
|
* MAY override
|
||||||
|
*
|
||||||
|
* @param array $args other arguments
|
||||||
|
*
|
||||||
|
* @return boolean is read only action?
|
||||||
|
*/
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
|
||||||
|
$_SERVER['REQUEST_METHOD'] == 'HEAD') {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return last modified, if applicable.
|
||||||
|
*
|
||||||
|
* MAY override
|
||||||
|
*
|
||||||
|
* @return string last modified http header
|
||||||
|
*/
|
||||||
|
function lastModified()
|
||||||
|
{
|
||||||
|
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
||||||
|
return strtotime($this->notices[0]->created);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return etag, if applicable.
|
||||||
|
*
|
||||||
|
* MAY override
|
||||||
|
*
|
||||||
|
* @return string etag http header
|
||||||
|
*/
|
||||||
|
function etag()
|
||||||
|
{
|
||||||
|
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
||||||
|
|
||||||
|
$last = count($this->notices) - 1;
|
||||||
|
|
||||||
|
return '"' . implode(
|
||||||
|
':',
|
||||||
|
array($this->arg('action'),
|
||||||
|
common_user_cache_hash($this->auth_user),
|
||||||
|
common_language(),
|
||||||
|
$this->user->id,
|
||||||
|
strtotime($this->notices[0]->created),
|
||||||
|
strtotime($this->notices[$last]->created))
|
||||||
|
)
|
||||||
|
. '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does this require authentication?
|
||||||
|
*
|
||||||
|
* @return boolean true if delete, else false
|
||||||
|
*/
|
||||||
|
function requiresAuth()
|
||||||
|
{
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
|
||||||
|
$_SERVER['REQUEST_METHOD'] == 'HEAD') {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
99
api-changes-1.1.1/actions/apiexternalprofileshow.php
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StatusNet, the distributed open-source microblogging tool
|
||||||
|
*
|
||||||
|
* Show an external user's profile information
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* @category API
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Hannes Mannerheim <h@nnesmannerhe.im>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('STATUSNET')) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once INSTALLDIR . '/lib/apiprivateauth.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ouputs information for a user, specified by ID or screen name.
|
||||||
|
* The user's most recent status will be returned inline.
|
||||||
|
*/
|
||||||
|
class ApiExternalProfileShowAction extends ApiPrivateAuthAction
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Take arguments for running
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST args
|
||||||
|
*
|
||||||
|
* @return boolean success flag
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
function prepare($args)
|
||||||
|
{
|
||||||
|
parent::prepare($args);
|
||||||
|
|
||||||
|
$profileurl = urldecode($this->arg('profileurl'));
|
||||||
|
|
||||||
|
$this->profile = Profile::staticGet('profileurl', $profileurl);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the request
|
||||||
|
*
|
||||||
|
* Check the format and show the user info
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST data (unused)
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function handle($args)
|
||||||
|
{
|
||||||
|
parent::handle($args);
|
||||||
|
|
||||||
|
if (empty($this->profile)) {
|
||||||
|
// TRANS: Client error displayed when requesting profile information for a non-existing profile.
|
||||||
|
$this->clientError(_('Profile not found.'), 404, 'json');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$twitter_user = $this->twitterUserArray($this->profile, true);
|
||||||
|
|
||||||
|
$this->initDocument('json');
|
||||||
|
$this->showJsonObjects($twitter_user);
|
||||||
|
$this->endDocument('json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if read only.
|
||||||
|
*
|
||||||
|
* MAY override
|
||||||
|
*
|
||||||
|
* @param array $args other arguments
|
||||||
|
*
|
||||||
|
* @return boolean is read only action?
|
||||||
|
*/
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
143
api-changes-1.1.1/actions/apisearchjson.php
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StatusNet, the distributed open-source microblogging tool
|
||||||
|
*
|
||||||
|
* Action for showing Twitter-like JSON search results
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* @category Search
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Zach Copley <zach@status.net>
|
||||||
|
* @copyright 2008-2010 StatusNet, Inc.
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once INSTALLDIR.'/lib/apiprivateauth.php';
|
||||||
|
require_once INSTALLDIR.'/lib/jsonsearchresultslist.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action handler for Twitter-compatible API search
|
||||||
|
*
|
||||||
|
* @category Search
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Zach Copley <zach@status.net>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
* @see ApiAction
|
||||||
|
*/
|
||||||
|
class ApiSearchJSONAction extends ApiPrivateAuthAction
|
||||||
|
{
|
||||||
|
var $query;
|
||||||
|
var $lang;
|
||||||
|
var $rpp;
|
||||||
|
var $page;
|
||||||
|
var $since_id;
|
||||||
|
var $limit;
|
||||||
|
var $geocode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialization.
|
||||||
|
*
|
||||||
|
* @param array $args Web and URL arguments
|
||||||
|
*
|
||||||
|
* @return boolean true if nothing goes wrong
|
||||||
|
*/
|
||||||
|
function prepare($args)
|
||||||
|
{
|
||||||
|
parent::prepare($args);
|
||||||
|
|
||||||
|
$this->query = $this->trimmed('q');
|
||||||
|
$this->lang = $this->trimmed('lang');
|
||||||
|
$this->rpp = $this->trimmed('rpp');
|
||||||
|
|
||||||
|
if (!$this->rpp) {
|
||||||
|
$this->rpp = 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->rpp > 100) {
|
||||||
|
$this->rpp = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->page = $this->trimmed('page');
|
||||||
|
|
||||||
|
if (!$this->page) {
|
||||||
|
$this->page = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Suppport max_id -- we need to tweak the backend
|
||||||
|
// Search classes to support it.
|
||||||
|
|
||||||
|
$this->since_id = $this->trimmed('since_id');
|
||||||
|
$this->geocode = $this->trimmed('geocode');
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a request
|
||||||
|
*
|
||||||
|
* @param array $args Arguments from $_REQUEST
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function handle($args)
|
||||||
|
{
|
||||||
|
parent::handle($args);
|
||||||
|
$this->showResults();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show search results
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function showResults()
|
||||||
|
{
|
||||||
|
// TODO: Support search operators like from: and to:, boolean, etc.
|
||||||
|
|
||||||
|
$notice = new Notice();
|
||||||
|
|
||||||
|
// lcase it for comparison
|
||||||
|
$q = strtolower($this->query);
|
||||||
|
|
||||||
|
$this->notices = array();
|
||||||
|
$search_engine = $notice->getSearchEngine('notice');
|
||||||
|
$search_engine->set_sort_mode('chron');
|
||||||
|
$search_engine->limit(($this->page - 1) * $this->rpp, $this->rpp + 1);
|
||||||
|
if ($search_engine->query($q)) {
|
||||||
|
$cnt = $notice->find();
|
||||||
|
$this->notices = $notice->fetchAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->showJsonTimeline($this->notices);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do we need to write to the database?
|
||||||
|
*
|
||||||
|
* @return boolean true
|
||||||
|
*/
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
139
api-changes-1.1.1/actions/apistatusesfavs.php
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StatusNet, the distributed open-source microblogging tool
|
||||||
|
*
|
||||||
|
* Show up to 100 favs of a notice
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* @category API
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Hannes Mannerheim <h@nnesmannerhe.im>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('STATUSNET')) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once INSTALLDIR . '/lib/apiauth.php';
|
||||||
|
require_once INSTALLDIR . '/lib/mediafile.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show up to 100 favs of a notice
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class ApiStatusesFavsAction extends ApiAuthAction
|
||||||
|
{
|
||||||
|
const MAXCOUNT = 100;
|
||||||
|
|
||||||
|
var $original = null;
|
||||||
|
var $cnt = self::MAXCOUNT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take arguments for running
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST args
|
||||||
|
*
|
||||||
|
* @return boolean success flag
|
||||||
|
*/
|
||||||
|
function prepare($args)
|
||||||
|
{
|
||||||
|
parent::prepare($args);
|
||||||
|
|
||||||
|
$id = $this->trimmed('id');
|
||||||
|
|
||||||
|
$this->original = Notice::staticGet('id', $id);
|
||||||
|
|
||||||
|
if (empty($this->original)) {
|
||||||
|
// TRANS: Client error displayed trying to display redents of a non-exiting notice.
|
||||||
|
$this->clientError(_('No such notice.'),
|
||||||
|
400, $this->format);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cnt = $this->trimmed('count');
|
||||||
|
|
||||||
|
if (empty($cnt) || !is_integer($cnt)) {
|
||||||
|
$cnt = 100;
|
||||||
|
} else {
|
||||||
|
$this->cnt = min((int)$cnt, self::MAXCOUNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the request
|
||||||
|
*
|
||||||
|
* Get favs and return them as json object
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST data (unused)
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function handle($args)
|
||||||
|
{
|
||||||
|
parent::handle($args);
|
||||||
|
|
||||||
|
$fave = new Fave();
|
||||||
|
$fave->selectAdd();
|
||||||
|
$fave->selectAdd('user_id');
|
||||||
|
$fave->notice_id = $this->original->id;
|
||||||
|
$fave->orderBy('modified');
|
||||||
|
if (!is_null($this->cnt)) {
|
||||||
|
$fave->limit(0, $this->cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ids = $fave->fetchAll('user_id');
|
||||||
|
|
||||||
|
// get nickname and profile image
|
||||||
|
$ids_with_profile_data = array();
|
||||||
|
$i=0;
|
||||||
|
foreach($ids as $id) {
|
||||||
|
$profile = Profile::staticGet('id', $id);
|
||||||
|
$ids_with_profile_data[$i]['user_id'] = $id;
|
||||||
|
$ids_with_profile_data[$i]['nickname'] = $profile->nickname;
|
||||||
|
$ids_with_profile_data[$i]['fullname'] = $profile->fullname;
|
||||||
|
$ids_with_profile_data[$i]['profileurl'] = $profile->profileurl;
|
||||||
|
$profile = new Profile();
|
||||||
|
$profile->id = $id;
|
||||||
|
$avatarurl = $profile->avatarUrl(24);
|
||||||
|
$ids_with_profile_data[$i]['avatarurl'] = $avatarurl;
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->initDocument('json');
|
||||||
|
$this->showJsonObjects($ids_with_profile_data);
|
||||||
|
$this->endDocument('json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if read only.
|
||||||
|
*
|
||||||
|
* MAY override
|
||||||
|
*
|
||||||
|
* @param array $args other arguments
|
||||||
|
*
|
||||||
|
* @return boolean is read only action?
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
380
api-changes-1.1.1/actions/apistatusesupdate.php
Normal file
|
@ -0,0 +1,380 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StatusNet, the distributed open-source microblogging tool
|
||||||
|
*
|
||||||
|
* Post a notice (update your status) through the API
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* @category API
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Craig Andrews <candrews@integralblue.com>
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @author Jeffery To <jeffery.to@gmail.com>
|
||||||
|
* @author Tom Blankenship <mac65@mac65.com>
|
||||||
|
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
||||||
|
* @author Robin Millette <robin@millette.info>
|
||||||
|
* @author Zach Copley <zach@status.net>
|
||||||
|
* @copyright 2009-2010 StatusNet, Inc.
|
||||||
|
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* External API usage documentation. Please update when you change how this method works. */
|
||||||
|
|
||||||
|
/*! @page statusesupdate statuses/update
|
||||||
|
|
||||||
|
@section Description
|
||||||
|
Updates the authenticating user's status. Requires the status parameter specified below.
|
||||||
|
Request must be a POST.
|
||||||
|
|
||||||
|
@par URL pattern
|
||||||
|
/api/statuses/update.:format
|
||||||
|
|
||||||
|
@par Formats (:format)
|
||||||
|
xml, json
|
||||||
|
|
||||||
|
@par HTTP Method(s)
|
||||||
|
POST
|
||||||
|
|
||||||
|
@par Requires Authentication
|
||||||
|
Yes
|
||||||
|
|
||||||
|
@param status (Required) The URL-encoded text of the status update.
|
||||||
|
@param source (Optional) The source application name, if using HTTP authentication or an anonymous OAuth consumer.
|
||||||
|
@param in_reply_to_status_id (Optional) The ID of an existing status that the update is in reply to.
|
||||||
|
@param lat (Optional) The latitude the status refers to.
|
||||||
|
@param long (Optional) The longitude the status refers to.
|
||||||
|
@param media (Optional) a media upload, such as an image or movie file.
|
||||||
|
|
||||||
|
@sa @ref authentication
|
||||||
|
@sa @ref apiroot
|
||||||
|
|
||||||
|
@subsection usagenotes Usage notes
|
||||||
|
|
||||||
|
@li The URL pattern is relative to the @ref apiroot.
|
||||||
|
@li If the @e source parameter is not supplied the source of the status will default to 'api'. When authenticated via a registered OAuth application, the application's registered name and URL will always override the source parameter.
|
||||||
|
@li The XML response uses <a href="http://georss.org/Main_Page">GeoRSS</a>
|
||||||
|
to encode the latitude and longitude (see example response below <georss:point>).
|
||||||
|
@li Data uploaded via the @e media parameter should be multipart/form-data encoded.
|
||||||
|
|
||||||
|
@subsection exampleusage Example usage
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
curl -u username:password http://example.com/api/statuses/update.xml -d status='Howdy!' -d lat='30.468' -d long='-94.743'
|
||||||
|
@endverbatim
|
||||||
|
|
||||||
|
@subsection exampleresponse Example response
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<status>
|
||||||
|
<text>Howdy!</text>
|
||||||
|
<truncated>false</truncated>
|
||||||
|
<created_at>Tue Mar 30 23:28:05 +0000 2010</created_at>
|
||||||
|
<in_reply_to_status_id/>
|
||||||
|
<source>api</source>
|
||||||
|
<id>26668724</id>
|
||||||
|
<in_reply_to_user_id/>
|
||||||
|
<in_reply_to_screen_name/>
|
||||||
|
<geo xmlns:georss="http://www.georss.org/georss">
|
||||||
|
<georss:point>30.468 -94.743</georss:point>
|
||||||
|
</geo>
|
||||||
|
<favorited>false</favorited>
|
||||||
|
<user>
|
||||||
|
<id>25803</id>
|
||||||
|
<name>Jed Sanders</name>
|
||||||
|
<screen_name>jedsanders</screen_name>
|
||||||
|
<location>Hoop and Holler, Texas</location>
|
||||||
|
<description>I like to think of myself as America's Favorite.</description>
|
||||||
|
<profile_image_url>http://avatar.example.com/25803-48-20080924200604.png</profile_image_url>
|
||||||
|
<url>http://jedsanders.net</url>
|
||||||
|
<protected>false</protected>
|
||||||
|
<followers_count>5</followers_count>
|
||||||
|
<profile_background_color/>
|
||||||
|
<profile_text_color/>
|
||||||
|
<profile_link_color/>
|
||||||
|
<profile_sidebar_fill_color/>
|
||||||
|
<profile_sidebar_border_color/>
|
||||||
|
<friends_count>2</friends_count>
|
||||||
|
<created_at>Wed Sep 24 20:04:00 +0000 2008</created_at>
|
||||||
|
<favourites_count>0</favourites_count>
|
||||||
|
<utc_offset>0</utc_offset>
|
||||||
|
<time_zone>UTC</time_zone>
|
||||||
|
<profile_background_image_url/>
|
||||||
|
<profile_background_tile>false</profile_background_tile>
|
||||||
|
<statuses_count>70</statuses_count>
|
||||||
|
<following>true</following>
|
||||||
|
<notifications>true</notifications>
|
||||||
|
</user>
|
||||||
|
</status>
|
||||||
|
@endverbatim
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('STATUSNET')) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once INSTALLDIR . '/lib/apiauth.php';
|
||||||
|
require_once INSTALLDIR . '/lib/mediafile.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the authenticating user's status (posts a notice).
|
||||||
|
*
|
||||||
|
* @category API
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Craig Andrews <candrews@integralblue.com>
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @author Jeffery To <jeffery.to@gmail.com>
|
||||||
|
* @author Tom Blankenship <mac65@mac65.com>
|
||||||
|
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
||||||
|
* @author Robin Millette <robin@millette.info>
|
||||||
|
* @author Zach Copley <zach@status.net>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
class ApiStatusesUpdateAction extends ApiAuthAction
|
||||||
|
{
|
||||||
|
var $status = null;
|
||||||
|
var $in_reply_to_status_id = null;
|
||||||
|
var $lat = null;
|
||||||
|
var $lon = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take arguments for running
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST args
|
||||||
|
*
|
||||||
|
* @return boolean success flag
|
||||||
|
*/
|
||||||
|
function prepare($args)
|
||||||
|
{
|
||||||
|
parent::prepare($args);
|
||||||
|
|
||||||
|
$this->status = $this->trimmed('status');
|
||||||
|
$this->lat = $this->trimmed('lat');
|
||||||
|
$this->lon = $this->trimmed('long');
|
||||||
|
|
||||||
|
$this->in_reply_to_status_id
|
||||||
|
= intval($this->trimmed('in_reply_to_status_id'));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the request
|
||||||
|
*
|
||||||
|
* Make a new notice for the update, save it, and show it
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST data (unused)
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function handle($args)
|
||||||
|
{
|
||||||
|
parent::handle($args);
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
|
||||||
|
$this->clientError(
|
||||||
|
// TRANS: Client error. POST is a HTTP command. It should not be translated.
|
||||||
|
_('This method requires a POST.'),
|
||||||
|
400,
|
||||||
|
$this->format
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Workaround for PHP returning empty $_POST and $_FILES when POST
|
||||||
|
// length > post_max_size in php.ini
|
||||||
|
|
||||||
|
if (empty($_FILES)
|
||||||
|
&& empty($_POST)
|
||||||
|
&& ($_SERVER['CONTENT_LENGTH'] > 0)
|
||||||
|
) {
|
||||||
|
// TRANS: Client error displayed when the number of bytes in a POST request exceeds a limit.
|
||||||
|
// TRANS: %s is the number of bytes of the CONTENT_LENGTH.
|
||||||
|
$msg = _m('The server was unable to handle that much POST data (%s byte) due to its current configuration.',
|
||||||
|
'The server was unable to handle that much POST data (%s bytes) due to its current configuration.',
|
||||||
|
intval($_SERVER['CONTENT_LENGTH']));
|
||||||
|
|
||||||
|
$this->clientError(sprintf($msg, $_SERVER['CONTENT_LENGTH']));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($this->status)) {
|
||||||
|
$this->clientError(
|
||||||
|
// TRANS: Client error displayed when the parameter "status" is missing.
|
||||||
|
_('Client must provide a \'status\' parameter with a value.'),
|
||||||
|
400,
|
||||||
|
$this->format
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($this->auth_user)) {
|
||||||
|
// TRANS: Client error displayed when updating a status for a non-existing user.
|
||||||
|
$this->clientError(_('No such user.'), 404, $this->format);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do not call shortenlinks until the whole notice has been build */
|
||||||
|
|
||||||
|
// Check for commands
|
||||||
|
|
||||||
|
$inter = new CommandInterpreter();
|
||||||
|
$cmd = $inter->handle_command($this->auth_user, $this->status);
|
||||||
|
|
||||||
|
if ($cmd) {
|
||||||
|
if ($this->supported($cmd)) {
|
||||||
|
$cmd->execute(new Channel());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cmd not supported? Twitter just returns your latest status.
|
||||||
|
// And, it returns your last status whether the cmd was successful
|
||||||
|
// or not!
|
||||||
|
|
||||||
|
$this->notice = $this->auth_user->getCurrentNotice();
|
||||||
|
} else {
|
||||||
|
$reply_to = null;
|
||||||
|
|
||||||
|
if (!empty($this->in_reply_to_status_id)) {
|
||||||
|
// Check whether notice actually exists
|
||||||
|
|
||||||
|
$reply = Notice::staticGet($this->in_reply_to_status_id);
|
||||||
|
|
||||||
|
if ($reply) {
|
||||||
|
$reply_to = $this->in_reply_to_status_id;
|
||||||
|
} else {
|
||||||
|
$this->clientError(
|
||||||
|
// TRANS: Client error displayed when replying to a non-existing notice.
|
||||||
|
_('Parent notice not found.'),
|
||||||
|
$code = 404,
|
||||||
|
$this->format
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$upload = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$upload = MediaFile::fromUpload('media', $this->auth_user);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->clientError($e->getMessage(), $e->getCode(), $this->format);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($upload)) {
|
||||||
|
$this->status .= ' ' . $upload->shortUrl();
|
||||||
|
|
||||||
|
/* Do not call shortenlinks until the whole notice has been build */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do call shortenlinks here & check notice length since notice is about to be saved & sent */
|
||||||
|
//$status_shortened = $this->auth_user->shortenlinks($this->status);
|
||||||
|
|
||||||
|
/* DO NOT! */
|
||||||
|
$status_shortened = $this->status;
|
||||||
|
|
||||||
|
if (Notice::contentTooLong($status_shortened)) {
|
||||||
|
if (isset($upload)) {
|
||||||
|
$upload->delete();
|
||||||
|
}
|
||||||
|
// TRANS: Client error displayed exceeding the maximum notice length.
|
||||||
|
// TRANS: %d is the maximum lenth for a notice.
|
||||||
|
$msg = _m('Maximum notice size is %d character, including attachment URL.',
|
||||||
|
'Maximum notice size is %d characters, including attachment URL.',
|
||||||
|
Notice::maxContent());
|
||||||
|
/* Use HTTP 413 error code (Request Entity Too Large)
|
||||||
|
* instead of basic 400 for better understanding
|
||||||
|
*/
|
||||||
|
$this->clientError(sprintf($msg, Notice::maxContent()),
|
||||||
|
413,
|
||||||
|
$this->format);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$content = html_entity_decode($status_shortened, ENT_NOQUOTES, 'UTF-8');
|
||||||
|
|
||||||
|
$options = array('reply_to' => $reply_to);
|
||||||
|
|
||||||
|
if ($this->auth_user->shareLocation()) {
|
||||||
|
|
||||||
|
$locOptions = Notice::locationOptions($this->lat,
|
||||||
|
$this->lon,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
$this->auth_user->getProfile());
|
||||||
|
|
||||||
|
$options = array_merge($options, $locOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->notice = Notice::saveNew(
|
||||||
|
$this->auth_user->id,
|
||||||
|
$content,
|
||||||
|
$this->source,
|
||||||
|
$options
|
||||||
|
);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->clientError($e->getMessage(), $e->getCode(), $this->format);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($upload)) {
|
||||||
|
$upload->attachToNotice($this->notice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->showNotice();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the resulting notice
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function showNotice()
|
||||||
|
{
|
||||||
|
if (!empty($this->notice)) {
|
||||||
|
if ($this->format == 'xml') {
|
||||||
|
$this->showSingleXmlStatus($this->notice);
|
||||||
|
} elseif ($this->format == 'json') {
|
||||||
|
$this->show_single_json_status($this->notice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this command supported when doing an update from the API?
|
||||||
|
*
|
||||||
|
* @param string $cmd the command to check for
|
||||||
|
*
|
||||||
|
* @return boolean true or false
|
||||||
|
*/
|
||||||
|
function supported($cmd)
|
||||||
|
{
|
||||||
|
static $cmdlist = array('MessageCommand', 'SubCommand', 'UnsubCommand',
|
||||||
|
'FavCommand', 'OnCommand', 'OffCommand', 'JoinCommand', 'LeaveCommand');
|
||||||
|
|
||||||
|
if (in_array(get_class($cmd), $cmdlist)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
248
api-changes-1.1.1/actions/apitimelinetag.php
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StatusNet, the distributed open-source microblogging tool
|
||||||
|
*
|
||||||
|
* Show the latest notices for a given tag
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* @category API
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Craig Andrews <candrews@integralblue.com>
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @author Jeffery To <jeffery.to@gmail.com>
|
||||||
|
* @author Zach Copley <zach@status.net>
|
||||||
|
* @copyright 2009-2010 StatusNet, Inc.
|
||||||
|
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('STATUSNET')) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once INSTALLDIR . '/lib/apiprivateauth.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the 20 most recent notices tagged by a given tag
|
||||||
|
*
|
||||||
|
* @category API
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Craig Andrews <candrews@integralblue.com>
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @author Jeffery To <jeffery.to@gmail.com>
|
||||||
|
* @author Zach Copley <zach@status.net>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
class ApiTimelineTagAction extends ApiPrivateAuthAction
|
||||||
|
{
|
||||||
|
var $notices = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take arguments for running
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST args
|
||||||
|
*
|
||||||
|
* @return boolean success flag
|
||||||
|
*/
|
||||||
|
function prepare($args)
|
||||||
|
{
|
||||||
|
parent::prepare($args);
|
||||||
|
|
||||||
|
common_debug("apitimelinetag prepare()");
|
||||||
|
|
||||||
|
$this->tag = $this->arg('tag');
|
||||||
|
$this->notices = $this->getNotices();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the request
|
||||||
|
*
|
||||||
|
* Just show the notices
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST data (unused)
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function handle($args)
|
||||||
|
{
|
||||||
|
parent::handle($args);
|
||||||
|
$this->showTimeline();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the timeline of notices
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function showTimeline()
|
||||||
|
{
|
||||||
|
$sitename = common_config('site', 'name');
|
||||||
|
$sitelogo = (common_config('site', 'logo')) ? common_config('site', 'logo') : Theme::path('logo.png');
|
||||||
|
// TRANS: Title for timeline with lastest notices with a given tag.
|
||||||
|
// TRANS: %s is the tag.
|
||||||
|
$title = sprintf(_("Notices tagged with %s"), $this->tag);
|
||||||
|
$subtitle = sprintf(
|
||||||
|
// TRANS: Subtitle for timeline with lastest notices with a given tag.
|
||||||
|
// TRANS: %1$s is the tag, $2$s is the StatusNet sitename.
|
||||||
|
_('Updates tagged with %1$s on %2$s!'),
|
||||||
|
$this->tag,
|
||||||
|
$sitename
|
||||||
|
);
|
||||||
|
$taguribase = TagURI::base();
|
||||||
|
$id = "tag:$taguribase:TagTimeline:".$this->tag;
|
||||||
|
|
||||||
|
$link = common_local_url(
|
||||||
|
'tag',
|
||||||
|
array('tag' => $this->tag)
|
||||||
|
);
|
||||||
|
|
||||||
|
$self = $this->getSelfUri();
|
||||||
|
|
||||||
|
switch($this->format) {
|
||||||
|
case 'xml':
|
||||||
|
$this->showXmlTimeline($this->notices);
|
||||||
|
break;
|
||||||
|
case 'rss':
|
||||||
|
$this->showRssTimeline(
|
||||||
|
$this->notices,
|
||||||
|
$title,
|
||||||
|
$link,
|
||||||
|
$subtitle,
|
||||||
|
null,
|
||||||
|
$sitelogo,
|
||||||
|
$self
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'atom':
|
||||||
|
header('Content-Type: application/atom+xml; charset=utf-8');
|
||||||
|
|
||||||
|
$atom = new AtomNoticeFeed($this->auth_user);
|
||||||
|
|
||||||
|
$atom->setId($id);
|
||||||
|
$atom->setTitle($title);
|
||||||
|
$atom->setSubtitle($subtitle);
|
||||||
|
$atom->setLogo($logo);
|
||||||
|
$atom->setUpdated('now');
|
||||||
|
|
||||||
|
$atom->addLink($link);
|
||||||
|
$atom->setSelfLink($self);
|
||||||
|
|
||||||
|
$atom->addEntryFromNotices($this->notices);
|
||||||
|
$this->raw($atom->getString());
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'json':
|
||||||
|
$this->showJsonTimeline($this->notices);
|
||||||
|
break;
|
||||||
|
case 'as':
|
||||||
|
header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE);
|
||||||
|
$doc = new ActivityStreamJSONDocument($this->auth_user);
|
||||||
|
$doc->setTitle($title);
|
||||||
|
$doc->addLink($link, 'alternate', 'text/html');
|
||||||
|
$doc->addItemsFromNotices($this->notices);
|
||||||
|
$this->raw($doc->asString());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// TRANS: Client error displayed when coming across a non-supported API method.
|
||||||
|
$this->clientError(_('API method not found.'), $code = 404);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get notices
|
||||||
|
*
|
||||||
|
* @return array notices
|
||||||
|
*/
|
||||||
|
function getNotices()
|
||||||
|
{
|
||||||
|
$notices = array();
|
||||||
|
|
||||||
|
$notice = Notice_tag::getStream(
|
||||||
|
$this->tag,
|
||||||
|
($this->page - 1) * $this->count,
|
||||||
|
$this->count + 1,
|
||||||
|
$this->since_id,
|
||||||
|
$this->max_id
|
||||||
|
);
|
||||||
|
|
||||||
|
while ($notice->fetch()) {
|
||||||
|
$notices[] = clone($notice);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $notices;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this action read only?
|
||||||
|
*
|
||||||
|
* @param array $args other arguments
|
||||||
|
*
|
||||||
|
* @return boolean true
|
||||||
|
*/
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When was this feed last modified?
|
||||||
|
*
|
||||||
|
* @return string datestamp of the latest notice in the stream
|
||||||
|
*/
|
||||||
|
function lastModified()
|
||||||
|
{
|
||||||
|
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
||||||
|
return strtotime($this->notices[0]->created);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An entity tag for this stream
|
||||||
|
*
|
||||||
|
* Returns an Etag based on the action name, language, and
|
||||||
|
* timestamps of the first and last notice in the timeline
|
||||||
|
*
|
||||||
|
* @return string etag
|
||||||
|
*/
|
||||||
|
function etag()
|
||||||
|
{
|
||||||
|
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
||||||
|
|
||||||
|
$last = count($this->notices) - 1;
|
||||||
|
|
||||||
|
return '"' . implode(
|
||||||
|
':',
|
||||||
|
array($this->arg('action'),
|
||||||
|
common_user_cache_hash($this->auth_user),
|
||||||
|
common_language(),
|
||||||
|
$this->tag,
|
||||||
|
strtotime($this->notices[0]->created),
|
||||||
|
strtotime($this->notices[$last]->created))
|
||||||
|
)
|
||||||
|
. '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
524
api-changes-1.1.1/actions/apitimelineuser.php
Normal file
|
@ -0,0 +1,524 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StatusNet, the distributed open-source microblogging tool
|
||||||
|
*
|
||||||
|
* Show a user's timeline
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* @category API
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Craig Andrews <candrews@integralblue.com>
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @author Jeffery To <jeffery.to@gmail.com>
|
||||||
|
* @author mac65 <mac65@mac65.com>
|
||||||
|
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
||||||
|
* @author Robin Millette <robin@millette.info>
|
||||||
|
* @author Zach Copley <zach@status.net>
|
||||||
|
* @copyright 2009 StatusNet, Inc.
|
||||||
|
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('STATUSNET')) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once INSTALLDIR . '/lib/apibareauth.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the most recent notices (default 20) posted by the authenticating
|
||||||
|
* user. Another user's timeline can be requested via the id parameter. This
|
||||||
|
* is the API equivalent of the user profile web page.
|
||||||
|
*
|
||||||
|
* @category API
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Craig Andrews <candrews@integralblue.com>
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @author Jeffery To <jeffery.to@gmail.com>
|
||||||
|
* @author mac65 <mac65@mac65.com>
|
||||||
|
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
||||||
|
* @author Robin Millette <robin@millette.info>
|
||||||
|
* @author Zach Copley <zach@status.net>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
class ApiTimelineUserAction extends ApiBareAuthAction
|
||||||
|
{
|
||||||
|
var $notices = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take arguments for running
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST args
|
||||||
|
*
|
||||||
|
* @return boolean success flag
|
||||||
|
*/
|
||||||
|
function prepare($args)
|
||||||
|
{
|
||||||
|
parent::prepare($args);
|
||||||
|
|
||||||
|
$this->user = $this->getTargetUser($this->arg('id'));
|
||||||
|
|
||||||
|
if (empty($this->user)) {
|
||||||
|
// TRANS: Client error displayed requesting most recent notices for a non-existing user.
|
||||||
|
$this->clientError(_('No such user.'), 404, $this->format);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->notices = $this->getNotices();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the request
|
||||||
|
*
|
||||||
|
* Just show the notices
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST data (unused)
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function handle($args)
|
||||||
|
{
|
||||||
|
parent::handle($args);
|
||||||
|
|
||||||
|
if ($this->isPost()) {
|
||||||
|
$this->handlePost();
|
||||||
|
} else {
|
||||||
|
$this->showTimeline();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the timeline of notices
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function showTimeline()
|
||||||
|
{
|
||||||
|
$profile = $this->user->getProfile();
|
||||||
|
|
||||||
|
// We'll use the shared params from the Atom stub
|
||||||
|
// for other feed types.
|
||||||
|
$atom = new AtomUserNoticeFeed($this->user, $this->auth_user);
|
||||||
|
|
||||||
|
$link = common_local_url(
|
||||||
|
'showstream',
|
||||||
|
array('nickname' => $this->user->nickname)
|
||||||
|
);
|
||||||
|
|
||||||
|
$self = $this->getSelfUri();
|
||||||
|
|
||||||
|
// FriendFeed's SUP protocol
|
||||||
|
// Also added RSS and Atom feeds
|
||||||
|
|
||||||
|
$suplink = common_local_url('sup', null, null, $this->user->id);
|
||||||
|
header('X-SUP-ID: ' . $suplink);
|
||||||
|
|
||||||
|
switch($this->format) {
|
||||||
|
case 'xml':
|
||||||
|
$this->showXmlTimeline($this->notices);
|
||||||
|
break;
|
||||||
|
case 'rss':
|
||||||
|
$this->showRssTimeline(
|
||||||
|
$this->notices,
|
||||||
|
$atom->title,
|
||||||
|
$link,
|
||||||
|
$atom->subtitle,
|
||||||
|
$suplink,
|
||||||
|
$atom->logo,
|
||||||
|
$self
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'atom':
|
||||||
|
header('Content-Type: application/atom+xml; charset=utf-8');
|
||||||
|
|
||||||
|
$atom->setId($self);
|
||||||
|
$atom->setSelfLink($self);
|
||||||
|
|
||||||
|
// Add navigation links: next, prev, first
|
||||||
|
// Note: we use IDs rather than pages for navigation; page boundaries
|
||||||
|
// change too quickly!
|
||||||
|
|
||||||
|
if (!empty($this->next_id)) {
|
||||||
|
$nextUrl = common_local_url('ApiTimelineUser',
|
||||||
|
array('format' => 'atom',
|
||||||
|
'id' => $this->user->id),
|
||||||
|
array('max_id' => $this->next_id));
|
||||||
|
|
||||||
|
$atom->addLink($nextUrl,
|
||||||
|
array('rel' => 'next',
|
||||||
|
'type' => 'application/atom+xml'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($this->page > 1 || !empty($this->max_id)) && !empty($this->notices)) {
|
||||||
|
|
||||||
|
$lastNotice = $this->notices[0];
|
||||||
|
$lastId = $lastNotice->id;
|
||||||
|
|
||||||
|
$prevUrl = common_local_url('ApiTimelineUser',
|
||||||
|
array('format' => 'atom',
|
||||||
|
'id' => $this->user->id),
|
||||||
|
array('since_id' => $lastId));
|
||||||
|
|
||||||
|
$atom->addLink($prevUrl,
|
||||||
|
array('rel' => 'prev',
|
||||||
|
'type' => 'application/atom+xml'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->page > 1 || !empty($this->since_id) || !empty($this->max_id)) {
|
||||||
|
|
||||||
|
$firstUrl = common_local_url('ApiTimelineUser',
|
||||||
|
array('format' => 'atom',
|
||||||
|
'id' => $this->user->id));
|
||||||
|
|
||||||
|
$atom->addLink($firstUrl,
|
||||||
|
array('rel' => 'first',
|
||||||
|
'type' => 'application/atom+xml'));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$atom->addEntryFromNotices($this->notices);
|
||||||
|
$this->raw($atom->getString());
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'json':
|
||||||
|
$this->showJsonTimeline($this->notices);
|
||||||
|
break;
|
||||||
|
case 'as':
|
||||||
|
header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE);
|
||||||
|
$doc = new ActivityStreamJSONDocument($this->auth_user);
|
||||||
|
$doc->setTitle($atom->title);
|
||||||
|
$doc->addLink($link, 'alternate', 'text/html');
|
||||||
|
$doc->addItemsFromNotices($this->notices);
|
||||||
|
|
||||||
|
// XXX: Add paging extension?
|
||||||
|
|
||||||
|
$this->raw($doc->asString());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// TRANS: Client error displayed when coming across a non-supported API method.
|
||||||
|
$this->clientError(_('API method not found.'), $code = 404);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get notices
|
||||||
|
*
|
||||||
|
* @return array notices
|
||||||
|
*/
|
||||||
|
function getNotices()
|
||||||
|
{
|
||||||
|
$notices = array();
|
||||||
|
|
||||||
|
$user_profile = $this->user->getProfile();
|
||||||
|
if(isset($this->auth_user)) {
|
||||||
|
$auth_user_profile = $this->auth_user->getProfile();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$auth_user_profile = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stream = new ProfileNoticeStream($user_profile, $auth_user_profile);
|
||||||
|
|
||||||
|
$notice = $stream->getNotices(($this->page-1) * $this->count,
|
||||||
|
$this->count + 1,
|
||||||
|
$this->since_id,
|
||||||
|
$this->max_id);
|
||||||
|
|
||||||
|
while ($notice->fetch()) {
|
||||||
|
if (count($notices) < $this->count) {
|
||||||
|
$notices[] = clone($notice);
|
||||||
|
} else {
|
||||||
|
$this->next_id = $notice->id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $notices;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We expose AtomPub here, so non-GET/HEAD reqs must be read/write.
|
||||||
|
*
|
||||||
|
* @param array $args other arguments
|
||||||
|
*
|
||||||
|
* @return boolean true
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When was this feed last modified?
|
||||||
|
*
|
||||||
|
* @return string datestamp of the latest notice in the stream
|
||||||
|
*/
|
||||||
|
function lastModified()
|
||||||
|
{
|
||||||
|
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
||||||
|
return strtotime($this->notices[0]->created);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An entity tag for this stream
|
||||||
|
*
|
||||||
|
* Returns an Etag based on the action name, language, user ID, and
|
||||||
|
* timestamps of the first and last notice in the timeline
|
||||||
|
*
|
||||||
|
* @return string etag
|
||||||
|
*/
|
||||||
|
function etag()
|
||||||
|
{
|
||||||
|
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
||||||
|
$last = count($this->notices) - 1;
|
||||||
|
|
||||||
|
return '"' . implode(
|
||||||
|
':',
|
||||||
|
array($this->arg('action'),
|
||||||
|
common_user_cache_hash($this->auth_user),
|
||||||
|
common_language(),
|
||||||
|
$this->user->id,
|
||||||
|
strtotime($this->notices[0]->created),
|
||||||
|
strtotime($this->notices[$last]->created))
|
||||||
|
)
|
||||||
|
. '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handlePost()
|
||||||
|
{
|
||||||
|
if (empty($this->auth_user) ||
|
||||||
|
$this->auth_user->id != $this->user->id) {
|
||||||
|
// TRANS: Client error displayed trying to add a notice to another user's timeline.
|
||||||
|
$this->clientError(_('Only the user can add to their own timeline.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only handle posts for Atom
|
||||||
|
if ($this->format != 'atom') {
|
||||||
|
// TRANS: Client error displayed when using another format than AtomPub.
|
||||||
|
$this->clientError(_('Only accept AtomPub for Atom feeds.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$xml = trim(file_get_contents('php://input'));
|
||||||
|
if (empty($xml)) {
|
||||||
|
// TRANS: Client error displayed attempting to post an empty API notice.
|
||||||
|
$this->clientError(_('Atom post must not be empty.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$old = error_reporting(error_reporting() & ~(E_WARNING | E_NOTICE));
|
||||||
|
$dom = new DOMDocument();
|
||||||
|
$ok = $dom->loadXML($xml);
|
||||||
|
error_reporting($old);
|
||||||
|
if (!$ok) {
|
||||||
|
// TRANS: Client error displayed attempting to post an API that is not well-formed XML.
|
||||||
|
$this->clientError(_('Atom post must be well-formed XML.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($dom->documentElement->namespaceURI != Activity::ATOM ||
|
||||||
|
$dom->documentElement->localName != 'entry') {
|
||||||
|
// TRANS: Client error displayed when not using an Atom entry.
|
||||||
|
$this->clientError(_('Atom post must be an Atom entry.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$activity = new Activity($dom->documentElement);
|
||||||
|
|
||||||
|
$saved = null;
|
||||||
|
|
||||||
|
if (Event::handle('StartAtomPubNewActivity', array(&$activity, $this->user, &$saved))) {
|
||||||
|
if ($activity->verb != ActivityVerb::POST) {
|
||||||
|
// TRANS: Client error displayed when not using the POST verb. Do not translate POST.
|
||||||
|
$this->clientError(_('Can only handle POST activities.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$note = $activity->objects[0];
|
||||||
|
|
||||||
|
if (!in_array($note->type, array(ActivityObject::NOTE,
|
||||||
|
ActivityObject::BLOGENTRY,
|
||||||
|
ActivityObject::STATUS))) {
|
||||||
|
// TRANS: Client error displayed when using an unsupported activity object type.
|
||||||
|
// TRANS: %s is the unsupported activity object type.
|
||||||
|
$this->clientError(sprintf(_('Cannot handle activity object type "%s".'),
|
||||||
|
$note->type));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$saved = $this->postNote($activity);
|
||||||
|
|
||||||
|
Event::handle('EndAtomPubNewActivity', array($activity, $this->user, $saved));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($saved)) {
|
||||||
|
header('HTTP/1.1 201 Created');
|
||||||
|
header("Location: " . common_local_url('ApiStatusesShow', array('id' => $saved->id,
|
||||||
|
'format' => 'atom')));
|
||||||
|
$this->showSingleAtomStatus($saved);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function postNote($activity)
|
||||||
|
{
|
||||||
|
$note = $activity->objects[0];
|
||||||
|
|
||||||
|
// Use summary as fallback for content
|
||||||
|
|
||||||
|
if (!empty($note->content)) {
|
||||||
|
$sourceContent = $note->content;
|
||||||
|
} else if (!empty($note->summary)) {
|
||||||
|
$sourceContent = $note->summary;
|
||||||
|
} else if (!empty($note->title)) {
|
||||||
|
$sourceContent = $note->title;
|
||||||
|
} else {
|
||||||
|
// @fixme fetch from $sourceUrl?
|
||||||
|
// TRANS: Client error displayed when posting a notice without content through the API.
|
||||||
|
// TRANS: %d is the notice ID (number).
|
||||||
|
$this->clientError(sprintf(_('No content for notice %d.'),
|
||||||
|
$note->id));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get (safe!) HTML and text versions of the content
|
||||||
|
|
||||||
|
$rendered = $this->purify($sourceContent);
|
||||||
|
$content = html_entity_decode(strip_tags($rendered), ENT_QUOTES, 'UTF-8');
|
||||||
|
|
||||||
|
$shortened = $this->auth_user->shortenLinks($content);
|
||||||
|
|
||||||
|
$options = array('is_local' => Notice::LOCAL_PUBLIC,
|
||||||
|
'rendered' => $rendered,
|
||||||
|
'replies' => array(),
|
||||||
|
'groups' => array(),
|
||||||
|
'tags' => array(),
|
||||||
|
'urls' => array());
|
||||||
|
|
||||||
|
// accept remote URI (not necessarily a good idea)
|
||||||
|
|
||||||
|
common_debug("Note ID is {$note->id}");
|
||||||
|
|
||||||
|
if (!empty($note->id)) {
|
||||||
|
$notice = Notice::staticGet('uri', trim($note->id));
|
||||||
|
|
||||||
|
if (!empty($notice)) {
|
||||||
|
// TRANS: Client error displayed when using another format than AtomPub.
|
||||||
|
// TRANS: %s is the notice URI.
|
||||||
|
$this->clientError(sprintf(_('Notice with URI "%s" already exists.'),
|
||||||
|
$note->id));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
common_log(LOG_NOTICE, "Saving client-supplied notice URI '$note->id'");
|
||||||
|
$options['uri'] = $note->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// accept remote create time (also maybe not such a good idea)
|
||||||
|
|
||||||
|
if (!empty($activity->time)) {
|
||||||
|
common_log(LOG_NOTICE, "Saving client-supplied create time {$activity->time}");
|
||||||
|
$options['created'] = common_sql_date($activity->time);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for optional attributes...
|
||||||
|
|
||||||
|
if (!empty($activity->context)) {
|
||||||
|
|
||||||
|
foreach ($activity->context->attention as $uri) {
|
||||||
|
|
||||||
|
$profile = Profile::fromURI($uri);
|
||||||
|
|
||||||
|
if (!empty($profile)) {
|
||||||
|
$options['replies'][] = $uri;
|
||||||
|
} else {
|
||||||
|
$group = User_group::staticGet('uri', $uri);
|
||||||
|
if (!empty($group)) {
|
||||||
|
$options['groups'][] = $group->id;
|
||||||
|
} else {
|
||||||
|
// @fixme: hook for discovery here
|
||||||
|
common_log(LOG_WARNING, sprintf('AtomPub post with unknown attention URI %s', $uri));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maintain direct reply associations
|
||||||
|
// @fixme what about conversation ID?
|
||||||
|
|
||||||
|
if (!empty($activity->context->replyToID)) {
|
||||||
|
$orig = Notice::staticGet('uri',
|
||||||
|
$activity->context->replyToID);
|
||||||
|
if (!empty($orig)) {
|
||||||
|
$options['reply_to'] = $orig->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$location = $activity->context->location;
|
||||||
|
|
||||||
|
if ($location) {
|
||||||
|
$options['lat'] = $location->lat;
|
||||||
|
$options['lon'] = $location->lon;
|
||||||
|
if ($location->location_id) {
|
||||||
|
$options['location_ns'] = $location->location_ns;
|
||||||
|
$options['location_id'] = $location->location_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Atom categories <-> hashtags
|
||||||
|
|
||||||
|
foreach ($activity->categories as $cat) {
|
||||||
|
if ($cat->term) {
|
||||||
|
$term = common_canonical_tag($cat->term);
|
||||||
|
if ($term) {
|
||||||
|
$options['tags'][] = $term;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Atom enclosures -> attachment URLs
|
||||||
|
foreach ($activity->enclosures as $href) {
|
||||||
|
// @fixme save these locally or....?
|
||||||
|
$options['urls'][] = $href;
|
||||||
|
}
|
||||||
|
|
||||||
|
$saved = Notice::saveNew($this->user->id,
|
||||||
|
$content,
|
||||||
|
'atompub', // TODO: deal with this
|
||||||
|
$options);
|
||||||
|
|
||||||
|
return $saved;
|
||||||
|
}
|
||||||
|
|
||||||
|
function purify($content)
|
||||||
|
{
|
||||||
|
require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php';
|
||||||
|
|
||||||
|
$config = array('safe' => 1,
|
||||||
|
'deny_attribute' => 'id,style,on*');
|
||||||
|
return htmLawed($content, $config);
|
||||||
|
}
|
||||||
|
}
|
2761
api-changes-1.1.1/classes/Notice.php
Normal file
1684
api-changes-1.1.1/lib/apiaction.php
Normal file
1193
api-changes-1.1.1/lib/router.php
Normal file
BIN
favicon.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
img/birds.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
img/birds_rtl.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
img/button_birds.png
Normal file
After Width: | Height: | Size: 736 B |
BIN
img/ekan4.jpg
Normal file
After Width: | Height: | Size: 268 KiB |
BIN
img/logo.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
img/sprite.png
Normal file
After Width: | Height: | Size: 9.2 KiB |
BIN
img/sprite_bgs.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
176
index.php
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
<?php include 'settings.php'; ?><!--
|
||||||
|
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· Q V I T T E R ·
|
||||||
|
· ·
|
||||||
|
· http://github.com/hannesmannerheim/qvitter ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· <o) ·
|
||||||
|
· /_//// ·
|
||||||
|
· (____/ ·
|
||||||
|
· (o< ·
|
||||||
|
· o> \\\\_\ ·
|
||||||
|
· \\) \____) ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· Qvitter is free software: you can redistribute it and / or modify it ·
|
||||||
|
· under the terms of the GNU Affero General Public License as published by ·
|
||||||
|
· the Free Software Foundation, either version three of the License or (at ·
|
||||||
|
· your option) any later version. ·
|
||||||
|
· ·
|
||||||
|
· Qvitter is distributed in hope that it will be useful but WITHOUT ANY ·
|
||||||
|
· WARRANTY; without even the implied warranty of MERCHANTABILTY or FITNESS ·
|
||||||
|
· FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for ·
|
||||||
|
· more details. ·
|
||||||
|
· ·
|
||||||
|
· You should have received a copy of the GNU Affero General Public License ·
|
||||||
|
· along with Qvitter. If not, see <http://www.gnu.org/licenses/>. ·
|
||||||
|
· ·
|
||||||
|
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
|
||||||
|
|
||||||
|
--><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<title><?php print $sitetitle; ?></title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="stylesheet" type="text/css" href="<?php print $qvitterpath; ?>css/1.css" />
|
||||||
|
<link rel="shortcut icon" type="image/x-icon" href="<?php print $qvitterpath; ?>favicon.ico">
|
||||||
|
<script>
|
||||||
|
window.timeBetweenPolling = <?php print $timebetweenpolling; ?>;
|
||||||
|
window.fullUrlToThisQvitterApp = '<?php print $qvitterpath; ?>';
|
||||||
|
window.siteRootDomain = '<?php print $siterootdomain; ?>';
|
||||||
|
window.useHistoryPushState = <?php if($usehistorypushstate) print 'true'; else print 'false'; ?>;
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="topbar">
|
||||||
|
<a id="logolink">
|
||||||
|
<div id="logo"></div>
|
||||||
|
<div class="dropdown-toggle">
|
||||||
|
<i class="nav-session"></i>
|
||||||
|
<b class="caret"></b>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<ul class="quitter-settings dropdown-menu">
|
||||||
|
<li class="dropdown-caret right">
|
||||||
|
<span class="caret-outer"></span>
|
||||||
|
<span class="caret-inner"></span>
|
||||||
|
</li>
|
||||||
|
<li><a id="logout"></a></li>
|
||||||
|
</ul>
|
||||||
|
<img id="birds-top" src="<?php print $qvitterpath; ?>img/birds.png" />
|
||||||
|
<div class="global-nav">
|
||||||
|
<div class="global-nav-inner">
|
||||||
|
<div class="container">
|
||||||
|
<div id="search">
|
||||||
|
<input type="text" spellcheck="false" autocomplete="off" name="q" placeholder="Sök" id="search-query" class="search-input">
|
||||||
|
<span class="search-icon">
|
||||||
|
<button class="icon nav-search" type="submit" tabindex="-1">
|
||||||
|
<span> Sök </span>
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
<input type="text" spellcheck="false" autocomplete="off" id="search-query-hint" class="search-input search-hinting-input" disabled="disabled">
|
||||||
|
</div>
|
||||||
|
<ul class="language-dropdown">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a class="dropdown-toggle">
|
||||||
|
<small></small>
|
||||||
|
<span class="current-language"></span>
|
||||||
|
<b class="caret"></b>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li class="dropdown-caret right">
|
||||||
|
<span class="caret-outer"></span>
|
||||||
|
<span class="caret-inner"></span>
|
||||||
|
</li>
|
||||||
|
<li><a class="language-link" title="Arabic" data-lang-code="ar">العربيّة</a></li>
|
||||||
|
<li><a class="language-link" title="German" data-lang-code="de">Deutsch</a></li>
|
||||||
|
<li><a class="language-link" title="English" data-lang-code="en">English</a></li>
|
||||||
|
<li><a class="language-link" title="Spanish" data-lang-code="es">Español</a></li>
|
||||||
|
<li><a class="language-link" title="Farsi" data-lang-code="fa">فارسی</a></li>
|
||||||
|
<li><a class="language-link" title="French" data-lang-code="fr">français</a></li>
|
||||||
|
<li><a class="language-link" title="Swedish" data-lang-code="sv">svenska</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="page-container">
|
||||||
|
<div id="user-container" style="display:none;">
|
||||||
|
<div id="login-content">
|
||||||
|
<div id="username-container">
|
||||||
|
<input id="username" type="text" value="" tabindex="1" />
|
||||||
|
</div>
|
||||||
|
<table class="password-signin"><tbody><tr>
|
||||||
|
<td class="flex-table-primary">
|
||||||
|
<div class="placeholding-input">
|
||||||
|
<input id="password" type="password" tabindex="2" value="" />
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="flex-table-secondary">
|
||||||
|
<button class="submit" type="submit" id="submit-login" tabindex="4"></button>
|
||||||
|
</td>
|
||||||
|
</tr></tbody></table>
|
||||||
|
<div id="remember-forgot">
|
||||||
|
<input type="checkbox" id="rememberme" name="rememberme" value="yes" tabindex="3"> <span id="rememberme_label"></span> · <a href="http://quitter.se/main/recoverpassword"></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="user-header">
|
||||||
|
<img id="user-avatar" src="" />
|
||||||
|
<div id="user-name"></div>
|
||||||
|
<div id="user-screen-name"></div>
|
||||||
|
<div id="user-profile-link"></div>
|
||||||
|
</div>
|
||||||
|
<div id="user-body">
|
||||||
|
<a><div id="user-queets"><strong></strong><div class="label"></div></div></a>
|
||||||
|
<a><div id="user-following"><strong></strong><div class="label"></div></div></a>
|
||||||
|
<a><div id="user-followers"><strong></strong><div class="label"></div></div></a>
|
||||||
|
<a><div id="user-groups"><strong></strong><div class="label"></div></div></a>
|
||||||
|
</div>
|
||||||
|
<div id="user-footer">
|
||||||
|
<div id="queet-box" class="queet-box"></div>
|
||||||
|
<div id="queet-toolbar">
|
||||||
|
<div id="queet-box-extras"></div>
|
||||||
|
<div id="queet-button">
|
||||||
|
<span id="queet-counter"></span>
|
||||||
|
<button id="queet"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="menu-container">
|
||||||
|
<div class="stream-selection" data-stream-header="" data-stream-name="statuses/friends_timeline.json"><i class="chev-right"></i></div>
|
||||||
|
<div class="stream-selection" data-stream-header="" data-stream-name="statuses/mentions.json"><i class="chev-right"></i></div>
|
||||||
|
<div class="stream-selection" data-stream-header="" data-stream-name="favorites.json"><i class="chev-right"></i></div>
|
||||||
|
<div class="stream-selection" data-stream-header="" data-stream-name="statuses/public_timeline.json"><i class="chev-right"></i></div>
|
||||||
|
</div>
|
||||||
|
<div class="menu-container" id="history-container"></div>
|
||||||
|
</div>
|
||||||
|
<div id="feed">
|
||||||
|
<div id="feed-header">
|
||||||
|
<div id="feed-header-inner">
|
||||||
|
<h2></h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="stream-item hidden"><div id="new-queets-bar"></div></div>
|
||||||
|
<div id="feed-body"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="footer"></div>
|
||||||
|
</div>
|
||||||
|
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/jquery-2.0.2.min.js"></script>
|
||||||
|
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/jquery-ui-1.10.3.min.js"></script>
|
||||||
|
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/jquery.easing.1.3.js"></script>
|
||||||
|
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/dom-functions-1.js"></script>
|
||||||
|
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/misc-functions-1.js"></script>
|
||||||
|
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/ajax-functions-1.js"></script>
|
||||||
|
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/qvitter-1.js"></script>
|
||||||
|
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/lan-1.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
397
js/ajax-functions-1.js
Normal file
|
@ -0,0 +1,397 @@
|
||||||
|
|
||||||
|
/* · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· Q V I T T E R ·
|
||||||
|
· ·
|
||||||
|
· http://github.com/hannesmannerheim/qvitter ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· <o) ·
|
||||||
|
· /_//// ·
|
||||||
|
· (____/ ·
|
||||||
|
· (o< ·
|
||||||
|
· o> \\\\_\ ·
|
||||||
|
· \\) \____) ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· Qvitter is free software: you can redistribute it and / or modify it ·
|
||||||
|
· under the terms of the GNU Affero General Public License as published by ·
|
||||||
|
· the Free Software Foundation, either version three of the License or (at ·
|
||||||
|
· your option) any later version. ·
|
||||||
|
· ·
|
||||||
|
· Qvitter is distributed in hope that it will be useful but WITHOUT ANY ·
|
||||||
|
· WARRANTY; without even the implied warranty of MERCHANTABILTY or FITNESS ·
|
||||||
|
· FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for ·
|
||||||
|
· more details. ·
|
||||||
|
· ·
|
||||||
|
· You should have received a copy of the GNU Affero General Public License ·
|
||||||
|
· along with Qvitter. If not, see <http://www.gnu.org/licenses/>. ·
|
||||||
|
· ·
|
||||||
|
· Contact h@nnesmannerhe.im if you have any questions. ·
|
||||||
|
· ·
|
||||||
|
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Check login credentials with http basic auth
|
||||||
|
·
|
||||||
|
· @param username: users screen name
|
||||||
|
· @param password: users password
|
||||||
|
· @param actionOnSuccess: callback function on log in success
|
||||||
|
·
|
||||||
|
· · · · · · · · · */
|
||||||
|
|
||||||
|
function checkLogin(username,password,actionOnSuccess) {
|
||||||
|
$.ajax({ url: window.fullUrlToThisQvitterApp + 'API.php',
|
||||||
|
type: 'POST',
|
||||||
|
data: {
|
||||||
|
getRequest: "account/verify_credentials.json",
|
||||||
|
username: username,
|
||||||
|
password: password
|
||||||
|
},
|
||||||
|
dataType: 'json',
|
||||||
|
success: function(data) {
|
||||||
|
if(typeof data.error == 'undefined') {
|
||||||
|
actionOnSuccess(data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
alert(data.error);
|
||||||
|
remove_spinner();
|
||||||
|
$('#submit-login').removeAttr('disabled');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Generic API GET request
|
||||||
|
·
|
||||||
|
· @param stream: any api get-request e.g. 'statuses/favs/111111.json'
|
||||||
|
· @param actionOnSuccess: callback function
|
||||||
|
·
|
||||||
|
· · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
function getFromAPI(stream, actionOnSuccess) {
|
||||||
|
|
||||||
|
// request without username/password
|
||||||
|
if(typeof window.loginUsername == 'undefined') {
|
||||||
|
$.ajax({ url: window.fullUrlToThisQvitterApp + 'API.php',
|
||||||
|
type: "POST",
|
||||||
|
data: {
|
||||||
|
getRequest: stream
|
||||||
|
},
|
||||||
|
dataType: 'json',
|
||||||
|
success: function(data) {
|
||||||
|
actionOnSuccess(data);
|
||||||
|
},
|
||||||
|
error: function(data) {
|
||||||
|
actionOnSuccess(false);
|
||||||
|
console.log(data);
|
||||||
|
remove_spinner();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// with username/password if set
|
||||||
|
else {
|
||||||
|
$.ajax({ url: window.fullUrlToThisQvitterApp + 'API.php',
|
||||||
|
type: "POST",
|
||||||
|
data: {
|
||||||
|
getRequest: stream,
|
||||||
|
username: window.loginUsername,
|
||||||
|
password: window.loginPassword
|
||||||
|
},
|
||||||
|
dataType: 'json',
|
||||||
|
success: function(data) {
|
||||||
|
actionOnSuccess(data);
|
||||||
|
},
|
||||||
|
error: function(data) {
|
||||||
|
actionOnSuccess(false);
|
||||||
|
console.log(data);
|
||||||
|
remove_spinner();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Post queet
|
||||||
|
·
|
||||||
|
· @param queetText_txt: the text to post
|
||||||
|
· @param actionOnSuccess: callback function, false on error, data on success
|
||||||
|
·
|
||||||
|
· · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
function postQueetToAPI(queetText_txt, actionOnSuccess) {
|
||||||
|
$.ajax({ url: window.fullUrlToThisQvitterApp + 'API.php',
|
||||||
|
type: "POST",
|
||||||
|
data: {
|
||||||
|
postRequest: 'statuses/update.json',
|
||||||
|
status: queetText_txt,
|
||||||
|
source: 'Qvitter',
|
||||||
|
username: window.loginUsername,
|
||||||
|
password: window.loginPassword
|
||||||
|
},
|
||||||
|
dataType: "json",
|
||||||
|
error: function(data){ actionOnSuccess(false); console.log(data); },
|
||||||
|
success: function(data) { actionOnSuccess(data);}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Post follow or unfollow user request
|
||||||
|
·
|
||||||
|
· @param followOrUnfollow: either 'follow' or 'unfollow'
|
||||||
|
· @param user_id: the user id of the user we want to follow
|
||||||
|
· @param actionOnSuccess: callback function, false on error, data on success
|
||||||
|
·
|
||||||
|
· · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
function APIFollowOrUnfollowUser(followOrUnfollow,user_id,this_element,actionOnSuccess) {
|
||||||
|
|
||||||
|
if(followOrUnfollow == 'follow') {
|
||||||
|
var postRequest = 'friendships/create.json';
|
||||||
|
}
|
||||||
|
else if (followOrUnfollow == 'unfollow') {
|
||||||
|
var postRequest = 'friendships/destroy.json';
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax({ url: window.fullUrlToThisQvitterApp + 'API.php',
|
||||||
|
type: "POST",
|
||||||
|
data: {
|
||||||
|
postRequest: postRequest,
|
||||||
|
user_id: user_id,
|
||||||
|
username: window.loginUsername,
|
||||||
|
password: window.loginPassword
|
||||||
|
},
|
||||||
|
dataType:"json",
|
||||||
|
error: function(data){ actionOnSuccess(false,this_element); console.log(data); },
|
||||||
|
success: function(data) { actionOnSuccess(data,this_element);}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Post join or leave group request
|
||||||
|
·
|
||||||
|
· @param joinOrLeave: either 'join' or 'leave'
|
||||||
|
· @param group_id: group's id
|
||||||
|
· @param actionOnSuccess: callback function, false on error, data on success
|
||||||
|
·
|
||||||
|
· · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
function APIJoinOrLeaveGroup(joinOrLeave,group_id,this_element,actionOnSuccess) {
|
||||||
|
$.ajax({ url: window.fullUrlToThisQvitterApp + 'API.php',
|
||||||
|
type: "POST",
|
||||||
|
data: {
|
||||||
|
postRequest: 'statusnet/groups/' + joinOrLeave + '.json',
|
||||||
|
id: group_id,
|
||||||
|
username: window.loginUsername,
|
||||||
|
password: window.loginPassword
|
||||||
|
},
|
||||||
|
dataType:"json",
|
||||||
|
error: function(data){ actionOnSuccess(false,this_element); console.log(data); },
|
||||||
|
success: function(data) { actionOnSuccess(data,this_element);}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Post reply
|
||||||
|
·
|
||||||
|
· @param queetText_txt: the text to post
|
||||||
|
· @param in_reply_to_status_id: the local id for the queet to reply to
|
||||||
|
· @param actionOnSuccess: callback function, false on error, data on success
|
||||||
|
·
|
||||||
|
· · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
function postReplyToAPI(queetText_txt, in_reply_to_status_id, actionOnSuccess) {
|
||||||
|
$.ajax({ url: window.fullUrlToThisQvitterApp + 'API.php',
|
||||||
|
type: "POST",
|
||||||
|
data: {
|
||||||
|
postRequest: 'statuses/update.json',
|
||||||
|
status: queetText_txt,
|
||||||
|
source: 'Qvitter',
|
||||||
|
username: window.loginUsername,
|
||||||
|
password: window.loginPassword,
|
||||||
|
in_reply_to_status_id: in_reply_to_status_id
|
||||||
|
},
|
||||||
|
dataType:"json",
|
||||||
|
error: function(data){ actionOnSuccess(false); console.log(data); },
|
||||||
|
success: function(data) { actionOnSuccess(data);}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Generic POST-action
|
||||||
|
·
|
||||||
|
· @param action: the api action, e.q. 'statuses/retweet/1.json'
|
||||||
|
· @param actionOnSuccess: callback function, false on error, data on success
|
||||||
|
·
|
||||||
|
· · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
function postActionToAPI(action, actionOnSuccess) {
|
||||||
|
$.ajax({ url: window.fullUrlToThisQvitterApp + 'API.php',
|
||||||
|
type: "POST",
|
||||||
|
data: {
|
||||||
|
postRequest: action,
|
||||||
|
source: 'Qvitter',
|
||||||
|
username: window.loginUsername,
|
||||||
|
password: window.loginPassword
|
||||||
|
},
|
||||||
|
dataType:"json",
|
||||||
|
error: function(data){ actionOnSuccess(false); console.log(data); },
|
||||||
|
success: function(data) { actionOnSuccess(data);}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Generic POST-action
|
||||||
|
·
|
||||||
|
· @param action: the api action, e.q. 'statuses/retweet/1.json'
|
||||||
|
· @param actionOnSuccess: callback function, false on error, data on success
|
||||||
|
·
|
||||||
|
· · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
function postActionToAPI(action, actionOnSuccess) {
|
||||||
|
$.ajax({ url: window.fullUrlToThisQvitterApp + 'API.php',
|
||||||
|
type: "POST",
|
||||||
|
data: {
|
||||||
|
postRequest: action,
|
||||||
|
source: 'Qvitter',
|
||||||
|
username: window.loginUsername,
|
||||||
|
password: window.loginPassword
|
||||||
|
},
|
||||||
|
dataType:"json",
|
||||||
|
error: function(data){ actionOnSuccess(false); console.log(data); },
|
||||||
|
success: function(data) { actionOnSuccess(data);}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Delete requeet
|
||||||
|
·
|
||||||
|
· @param this_stream_item: jQuery object for stream-item
|
||||||
|
· @param this_action: JQuery object for the requeet-button
|
||||||
|
· @param my_rq_id: the id for the requeet
|
||||||
|
·
|
||||||
|
· · · · · · · · · */
|
||||||
|
|
||||||
|
function unRequeet(this_stream_item, this_action, my_rq_id) {
|
||||||
|
this_action.children('.with-icn').removeClass('done');
|
||||||
|
this_action.find('.with-icn b').html(window.sL.requeetVerb);
|
||||||
|
this_stream_item.removeClass('requeeted');
|
||||||
|
|
||||||
|
// post unrequeet
|
||||||
|
postActionToAPI('statuses/destroy/' + my_rq_id + '.json', function(data) {
|
||||||
|
if(data) {
|
||||||
|
remove_spinner();
|
||||||
|
this_stream_item.removeAttr('data-requeeted-by-me-id');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
remove_spinner();
|
||||||
|
this_action.children('.with-icn').addClass('done');
|
||||||
|
this_action.find('.with-icn b').html(window.sL.requeetedVerb);
|
||||||
|
this_stream_item.addClass('requeeted');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Gets favs or requeets for a queet from api
|
||||||
|
·
|
||||||
|
· @param apiaction: i.e. 'favs' or 'requeets'
|
||||||
|
· @param qid: the queet id
|
||||||
|
· @param actionOnSuccess: callback function
|
||||||
|
·
|
||||||
|
· · · · · · · · · */
|
||||||
|
|
||||||
|
function getFavsOrRequeetsForQueet(apiaction,qid,actionOnSuccess) {
|
||||||
|
if(apiaction=="requeets") { apiaction="retweets"; } // we might mix this up...
|
||||||
|
$.ajax({ url: window.fullUrlToThisQvitterApp + 'API.php',
|
||||||
|
type: "POST",
|
||||||
|
data: {
|
||||||
|
getRequest: "statuses/" + apiaction + "/" + qid + ".json",
|
||||||
|
username: window.loginUsername,
|
||||||
|
password: window.loginPassword
|
||||||
|
},
|
||||||
|
dataType: 'json',
|
||||||
|
success: function(data) {
|
||||||
|
if(data.length > 0) {
|
||||||
|
actionOnSuccess(data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
actionOnSuccess(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(data) {
|
||||||
|
remove_spinner();
|
||||||
|
console.log(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Shorten urls in box
|
||||||
|
·
|
||||||
|
· @param apiaction: i.e. 'favs' or 'requeets'
|
||||||
|
· @param qid: the queet id
|
||||||
|
· @param actionOnSuccess: callback function
|
||||||
|
·
|
||||||
|
· params included to pass along to countCharsInQueetBox
|
||||||
|
·
|
||||||
|
· · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
function shortenUrlsInBox(box,cnt,btn) {
|
||||||
|
// wrap urls
|
||||||
|
// var allurls = findUrls(box.html().replace(/&/gi,'&').replace(/ /gi,' '));
|
||||||
|
// $.each(allurls,function(key,obj){
|
||||||
|
// if(obj.substring(0,15) != 'http://qttr.at/' && obj.length > 20) { // don't shorten if link is qttr.at or very short already
|
||||||
|
// box.html(box.html().replace(/&/gi,'&').replace(obj,'<a class="shortening">' + obj + '</a>'));
|
||||||
|
// placeCaretAtEnd(document.getElementById(box.attr('id')));
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// // shorten urls vith qttr.at
|
||||||
|
// $.each(box.find('a.shortening'),function(key,obj){
|
||||||
|
// display_spinner();
|
||||||
|
// var urlEncodedUrl = encodeURIComponent($(obj).html().replace(/&/gi,'&'));
|
||||||
|
// $.ajax({ url: "http://qttr.at/yourls-api.php?format=jsonp&action=shorturl&signature=b6afeec983&url=" + urlEncodedUrl, type: "GET", dataType: "jsonp", success: function(data) {
|
||||||
|
// if(typeof data.shorturl != 'undefined') {
|
||||||
|
// $(obj).before(data.shorturl);
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// $(obj).before($(obj).html());
|
||||||
|
// }
|
||||||
|
// $(obj).remove();
|
||||||
|
// remove_spinner();
|
||||||
|
// placeCaretAtEnd(document.getElementById(box.attr('id')));
|
||||||
|
// countCharsInQueetBox(box,cnt,btn);
|
||||||
|
// }});
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
1381
js/dom-functions-1.js
Normal file
6
js/jquery-2.0.2.min.js
vendored
Normal file
12
js/jquery-ui-1.10.3.min.js
vendored
Normal file
205
js/jquery.easing.1.3.js
Normal file
|
@ -0,0 +1,205 @@
|
||||||
|
/*
|
||||||
|
* jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
|
||||||
|
*
|
||||||
|
* Uses the built in easing capabilities added In jQuery 1.1
|
||||||
|
* to offer multiple easing options
|
||||||
|
*
|
||||||
|
* TERMS OF USE - jQuery Easing
|
||||||
|
*
|
||||||
|
* Open source under the BSD License.
|
||||||
|
*
|
||||||
|
* Copyright © 2008 George McGinley Smith
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* Neither the name of the author nor the names of contributors may be used to endorse
|
||||||
|
* or promote products derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||||
|
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// t: current time, b: begInnIng value, c: change In value, d: duration
|
||||||
|
jQuery.easing['jswing'] = jQuery.easing['swing'];
|
||||||
|
|
||||||
|
jQuery.extend( jQuery.easing,
|
||||||
|
{
|
||||||
|
def: 'easeOutQuad',
|
||||||
|
swing: function (x, t, b, c, d) {
|
||||||
|
//alert(jQuery.easing.default);
|
||||||
|
return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
|
||||||
|
},
|
||||||
|
easeInQuad: function (x, t, b, c, d) {
|
||||||
|
return c*(t/=d)*t + b;
|
||||||
|
},
|
||||||
|
easeOutQuad: function (x, t, b, c, d) {
|
||||||
|
return -c *(t/=d)*(t-2) + b;
|
||||||
|
},
|
||||||
|
easeInOutQuad: function (x, t, b, c, d) {
|
||||||
|
if ((t/=d/2) < 1) return c/2*t*t + b;
|
||||||
|
return -c/2 * ((--t)*(t-2) - 1) + b;
|
||||||
|
},
|
||||||
|
easeInCubic: function (x, t, b, c, d) {
|
||||||
|
return c*(t/=d)*t*t + b;
|
||||||
|
},
|
||||||
|
easeOutCubic: function (x, t, b, c, d) {
|
||||||
|
return c*((t=t/d-1)*t*t + 1) + b;
|
||||||
|
},
|
||||||
|
easeInOutCubic: function (x, t, b, c, d) {
|
||||||
|
if ((t/=d/2) < 1) return c/2*t*t*t + b;
|
||||||
|
return c/2*((t-=2)*t*t + 2) + b;
|
||||||
|
},
|
||||||
|
easeInQuart: function (x, t, b, c, d) {
|
||||||
|
return c*(t/=d)*t*t*t + b;
|
||||||
|
},
|
||||||
|
easeOutQuart: function (x, t, b, c, d) {
|
||||||
|
return -c * ((t=t/d-1)*t*t*t - 1) + b;
|
||||||
|
},
|
||||||
|
easeInOutQuart: function (x, t, b, c, d) {
|
||||||
|
if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
|
||||||
|
return -c/2 * ((t-=2)*t*t*t - 2) + b;
|
||||||
|
},
|
||||||
|
easeInQuint: function (x, t, b, c, d) {
|
||||||
|
return c*(t/=d)*t*t*t*t + b;
|
||||||
|
},
|
||||||
|
easeOutQuint: function (x, t, b, c, d) {
|
||||||
|
return c*((t=t/d-1)*t*t*t*t + 1) + b;
|
||||||
|
},
|
||||||
|
easeInOutQuint: function (x, t, b, c, d) {
|
||||||
|
if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
|
||||||
|
return c/2*((t-=2)*t*t*t*t + 2) + b;
|
||||||
|
},
|
||||||
|
easeInSine: function (x, t, b, c, d) {
|
||||||
|
return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
|
||||||
|
},
|
||||||
|
easeOutSine: function (x, t, b, c, d) {
|
||||||
|
return c * Math.sin(t/d * (Math.PI/2)) + b;
|
||||||
|
},
|
||||||
|
easeInOutSine: function (x, t, b, c, d) {
|
||||||
|
return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
|
||||||
|
},
|
||||||
|
easeInExpo: function (x, t, b, c, d) {
|
||||||
|
return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
|
||||||
|
},
|
||||||
|
easeOutExpo: function (x, t, b, c, d) {
|
||||||
|
return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
|
||||||
|
},
|
||||||
|
easeInOutExpo: function (x, t, b, c, d) {
|
||||||
|
if (t==0) return b;
|
||||||
|
if (t==d) return b+c;
|
||||||
|
if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
|
||||||
|
return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
|
||||||
|
},
|
||||||
|
easeInCirc: function (x, t, b, c, d) {
|
||||||
|
return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
|
||||||
|
},
|
||||||
|
easeOutCirc: function (x, t, b, c, d) {
|
||||||
|
return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
|
||||||
|
},
|
||||||
|
easeInOutCirc: function (x, t, b, c, d) {
|
||||||
|
if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
|
||||||
|
return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
|
||||||
|
},
|
||||||
|
easeInElastic: function (x, t, b, c, d) {
|
||||||
|
var s=1.70158;var p=0;var a=c;
|
||||||
|
if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
|
||||||
|
if (a < Math.abs(c)) { a=c; var s=p/4; }
|
||||||
|
else var s = p/(2*Math.PI) * Math.asin (c/a);
|
||||||
|
return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
|
||||||
|
},
|
||||||
|
easeOutElastic: function (x, t, b, c, d) {
|
||||||
|
var s=1.70158;var p=0;var a=c;
|
||||||
|
if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
|
||||||
|
if (a < Math.abs(c)) { a=c; var s=p/4; }
|
||||||
|
else var s = p/(2*Math.PI) * Math.asin (c/a);
|
||||||
|
return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
|
||||||
|
},
|
||||||
|
easeInOutElastic: function (x, t, b, c, d) {
|
||||||
|
var s=1.70158;var p=0;var a=c;
|
||||||
|
if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5);
|
||||||
|
if (a < Math.abs(c)) { a=c; var s=p/4; }
|
||||||
|
else var s = p/(2*Math.PI) * Math.asin (c/a);
|
||||||
|
if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
|
||||||
|
return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
|
||||||
|
},
|
||||||
|
easeInBack: function (x, t, b, c, d, s) {
|
||||||
|
if (s == undefined) s = 1.70158;
|
||||||
|
return c*(t/=d)*t*((s+1)*t - s) + b;
|
||||||
|
},
|
||||||
|
easeOutBack: function (x, t, b, c, d, s) {
|
||||||
|
if (s == undefined) s = 1.70158;
|
||||||
|
return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
|
||||||
|
},
|
||||||
|
easeInOutBack: function (x, t, b, c, d, s) {
|
||||||
|
if (s == undefined) s = 1.70158;
|
||||||
|
if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
|
||||||
|
return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
|
||||||
|
},
|
||||||
|
easeInBounce: function (x, t, b, c, d) {
|
||||||
|
return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
|
||||||
|
},
|
||||||
|
easeOutBounce: function (x, t, b, c, d) {
|
||||||
|
if ((t/=d) < (1/2.75)) {
|
||||||
|
return c*(7.5625*t*t) + b;
|
||||||
|
} else if (t < (2/2.75)) {
|
||||||
|
return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
|
||||||
|
} else if (t < (2.5/2.75)) {
|
||||||
|
return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
|
||||||
|
} else {
|
||||||
|
return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
easeInOutBounce: function (x, t, b, c, d) {
|
||||||
|
if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
|
||||||
|
return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* TERMS OF USE - EASING EQUATIONS
|
||||||
|
*
|
||||||
|
* Open source under the BSD License.
|
||||||
|
*
|
||||||
|
* Copyright © 2001 Robert Penner
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* Neither the name of the author nor the names of contributors may be used to endorse
|
||||||
|
* or promote products derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||||
|
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
703
js/lan-1.js
Normal file
|
@ -0,0 +1,703 @@
|
||||||
|
|
||||||
|
/* · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· Q V I T T E R ·
|
||||||
|
· ·
|
||||||
|
· http://github.com/hannesmannerheim/qvitter ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· <o) ·
|
||||||
|
· /_//// ·
|
||||||
|
· (____/ ·
|
||||||
|
· (o< ·
|
||||||
|
· o> \\\\_\ ·
|
||||||
|
· \\) \____) ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· Qvitter is free software: you can redistribute it and / or modify it ·
|
||||||
|
· under the terms of the GNU Affero General Public License as published by ·
|
||||||
|
· the Free Software Foundation, either version three of the License or (at ·
|
||||||
|
· your option) any later version. ·
|
||||||
|
· ·
|
||||||
|
· Qvitter is distributed in hope that it will be useful but WITHOUT ANY ·
|
||||||
|
· WARRANTY; without even the implied warranty of MERCHANTABILTY or FITNESS ·
|
||||||
|
· FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for ·
|
||||||
|
· more details. ·
|
||||||
|
· ·
|
||||||
|
· You should have received a copy of the GNU Affero General Public License ·
|
||||||
|
· along with Qvitter. If not, see <http://www.gnu.org/licenses/>. ·
|
||||||
|
· ·
|
||||||
|
· Contact h@nnesmannerhe.im if you have any questions. ·
|
||||||
|
· ·
|
||||||
|
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
// langages object
|
||||||
|
window.l = new Object();
|
||||||
|
|
||||||
|
|
||||||
|
// spanish
|
||||||
|
window.l.es = new Object();
|
||||||
|
window.l.es.languageName = 'Español';
|
||||||
|
window.l.es.loginUsername = 'Nombre de usuario o correo electrónico';
|
||||||
|
window.l.es.loginPassword = 'Contraseña';
|
||||||
|
window.l.es.loginSignIn = 'Iniciar sesión';
|
||||||
|
window.l.es.loginRememberMe = 'Recordar mis datos';
|
||||||
|
window.l.es.loginForgotPassword = '¿Olvidaste tu contraseña?';
|
||||||
|
window.l.es.notices = 'Queets';
|
||||||
|
window.l.es.followers = 'Seguidores';
|
||||||
|
window.l.es.following = 'Siguiendo';
|
||||||
|
window.l.es.groups = 'Grupos';
|
||||||
|
window.l.es.compose = 'Publicar un nuevo Queet...';
|
||||||
|
window.l.es.queetVerb = 'Quittear';
|
||||||
|
window.l.es.queetsNounPlural = 'Queets';
|
||||||
|
window.l.es.logout = 'Cerrar sesión';
|
||||||
|
window.l.es.languageSelected = 'Idioma:';
|
||||||
|
window.l.es.viewMyProfilePage = 'Ver mi página de perfil';
|
||||||
|
window.l.es.expand = 'Abrir';
|
||||||
|
window.l.es.collapse = 'Reducir';
|
||||||
|
window.l.es.details = 'Detalles';
|
||||||
|
window.l.es.expandFullConversation = 'Ver la conversación entera';
|
||||||
|
window.l.es.replyVerb = 'Responder';
|
||||||
|
window.l.es.requeetVerb = 'Requittear';
|
||||||
|
window.l.es.favoriteVerb = 'Favorito';
|
||||||
|
window.l.es.requeetedVerb = 'Requitteado';
|
||||||
|
window.l.es.favoritedVerb = 'Favorito';
|
||||||
|
window.l.es.replyTo = 'Responder a';
|
||||||
|
window.l.es.requeetedBy = 'Requitteado por';
|
||||||
|
window.l.es.favoriteNoun = 'Favorito';
|
||||||
|
window.l.es.favoritesNoun = 'Favoritos';
|
||||||
|
window.l.es.requeetNoun = 'Requeet';
|
||||||
|
window.l.es.requeetsNoun = 'Requeets';
|
||||||
|
window.l.es.newQueet = 'nuevo Queet';
|
||||||
|
window.l.es.newQueets = 'nuevos Queets';
|
||||||
|
window.l.es.longmonthsJanuary = "enero";
|
||||||
|
window.l.es.longmonthsFebruary = "febrero";
|
||||||
|
window.l.es.longmonthsMars = "marzo";
|
||||||
|
window.l.es.longmonthsApril = "abril";
|
||||||
|
window.l.es.longmonthsMay = "mayo";
|
||||||
|
window.l.es.longmonthsJune = "junio";
|
||||||
|
window.l.es.longmonthsJuly = "julio";
|
||||||
|
window.l.es.longmonthsAugust = "agosto";
|
||||||
|
window.l.es.longmonthsSeptember = "septiembre";
|
||||||
|
window.l.es.longmonthsOctober = "octubre";
|
||||||
|
window.l.es.longmonthsNovember = "noviembre";
|
||||||
|
window.l.es.longmonthsDecember = "diciembre";
|
||||||
|
window.l.es.shortmonthsJanuary = "enero";
|
||||||
|
window.l.es.shortmonthsFebruary = "feb";
|
||||||
|
window.l.es.shortmonthsMars = "marzo";
|
||||||
|
window.l.es.shortmonthsApril = "abr";
|
||||||
|
window.l.es.shortmonthsMay = "mayo";
|
||||||
|
window.l.es.shortmonthsJune = "jun";
|
||||||
|
window.l.es.shortmonthsJuly = "jul";
|
||||||
|
window.l.es.shortmonthsAugust = "agosto";
|
||||||
|
window.l.es.shortmonthsSeptember = "sept";
|
||||||
|
window.l.es.shortmonthsOctober = "oct";
|
||||||
|
window.l.es.shortmonthsNovember = "nov";
|
||||||
|
window.l.es.shortmonthsDecember = "dic";
|
||||||
|
window.l.es.time12am = '{time} AM';
|
||||||
|
window.l.es.time12pm = '{time} PM';
|
||||||
|
window.l.es.longDateFormat = '{time24} - {day} {month} {year}';
|
||||||
|
window.l.es.shortDateFormatSeconds = '{seconds}s';
|
||||||
|
window.l.es.shortDateFormatMinutes = '{minutes}min';
|
||||||
|
window.l.es.shortDateFormatHours = '{hours}h';
|
||||||
|
window.l.es.shortDateFormatDate = '{day} {month}';
|
||||||
|
window.l.es.shortDateFormatDateAndY = '{day} {month} {year}';
|
||||||
|
window.l.es.now = 'ahorita';
|
||||||
|
window.l.es.posting = 'enviando';
|
||||||
|
window.l.es.viewMoreInConvBefore = '← Ver más en la conversación';
|
||||||
|
window.l.es.viewMoreInConvAfter = 'Ver más en la conversación →';
|
||||||
|
window.l.es.mentions = 'Menciones';
|
||||||
|
window.l.es.publicTimeline = 'Línea temporal pública';
|
||||||
|
window.l.es.searchVerb = 'Buscar';
|
||||||
|
window.l.es.deleteVerb = 'Eliminar';
|
||||||
|
window.l.es.cancelVerb = 'Cancelar';
|
||||||
|
window.l.es.deleteConfirmation = '¿Estás seguro de que quieres eliminar este queet?';
|
||||||
|
window.l.es.userFollow = 'Seguir';
|
||||||
|
window.l.es.userFollowing = 'Siguiendo';
|
||||||
|
window.l.es.userUnfollow = 'Dejar de seguir';
|
||||||
|
window.l.es.joinGroup = 'Unirse al grupo';
|
||||||
|
window.l.es.isMemberOfGroup = 'Abandonar grupo';
|
||||||
|
window.l.es.leaveGroup = 'Abandonar grupo';
|
||||||
|
window.l.es.memberCount = 'Miembros';
|
||||||
|
window.l.es.adminCount = 'Administradores';
|
||||||
|
|
||||||
|
|
||||||
|
// french
|
||||||
|
window.l.fr = new Object();
|
||||||
|
window.l.fr.languageName = 'français';
|
||||||
|
window.l.fr.loginUsername = 'Nom d\'utilisateur ou email';
|
||||||
|
window.l.fr.loginPassword = 'Mot de passe';
|
||||||
|
window.l.fr.loginSignIn = 'Se connecter';
|
||||||
|
window.l.fr.loginRememberMe = 'Se souvenir de moi';
|
||||||
|
window.l.fr.loginForgotPassword = 'Mot de passe oublié ?';
|
||||||
|
window.l.fr.notices = 'Queets';
|
||||||
|
window.l.fr.followers = 'Abonnés';
|
||||||
|
window.l.fr.following = 'Abonnements';
|
||||||
|
window.l.fr.groups = 'Groupes';
|
||||||
|
window.l.fr.compose = 'Écrire un nouveau Queet...';
|
||||||
|
window.l.fr.queetVerb = 'Queeter';
|
||||||
|
window.l.fr.queetsNounPlural = 'Queets';
|
||||||
|
window.l.fr.logout = 'Déconnexion';
|
||||||
|
window.l.fr.languageSelected = 'Langue :';
|
||||||
|
window.l.fr.viewMyProfilePage = 'Voir ma page de profil';
|
||||||
|
window.l.fr.expand = 'Ouvrir';
|
||||||
|
window.l.fr.collapse = 'Réduire';
|
||||||
|
window.l.fr.details = 'Détails';
|
||||||
|
window.l.fr.expandFullConversation = 'montrer la totalité de la conversation';
|
||||||
|
window.l.fr.replyVerb = 'Répondre';
|
||||||
|
window.l.fr.requeetVerb = 'Requeeter';
|
||||||
|
window.l.fr.favoriteVerb = 'Favori';
|
||||||
|
window.l.fr.requeetedVerb = 'Requeeté';
|
||||||
|
window.l.fr.favoritedVerb = 'Ajouté aux favoris';
|
||||||
|
window.l.fr.replyTo = 'Répondre à';
|
||||||
|
window.l.fr.requeetedBy = 'Requeeté par';
|
||||||
|
window.l.fr.favoriteNoun = 'Favori';
|
||||||
|
window.l.fr.favoritesNoun = 'Favoris';
|
||||||
|
window.l.fr.requeetNoun = 'Requeet';
|
||||||
|
window.l.fr.requeetsNoun = 'Requeets';
|
||||||
|
window.l.fr.newQueet = 'nouveau Queet';
|
||||||
|
window.l.fr.newQueets = 'nouveaux Queets';
|
||||||
|
window.l.fr.longmonthsJanuary = "janvier";
|
||||||
|
window.l.fr.longmonthsFebruary = "février";
|
||||||
|
window.l.fr.longmonthsMars = "mars";
|
||||||
|
window.l.fr.longmonthsApril = "avril";
|
||||||
|
window.l.fr.longmonthsMay = "mai";
|
||||||
|
window.l.fr.longmonthsJune = "juin";
|
||||||
|
window.l.fr.longmonthsJuly = "juillet";
|
||||||
|
window.l.fr.longmonthsAugust = "août";
|
||||||
|
window.l.fr.longmonthsSeptember = "septembre";
|
||||||
|
window.l.fr.longmonthsOctober = "octobre";
|
||||||
|
window.l.fr.longmonthsNovember = "novembre";
|
||||||
|
window.l.fr.longmonthsDecember = "décembre";
|
||||||
|
window.l.fr.shortmonthsJanuary = "janv";
|
||||||
|
window.l.fr.shortmonthsFebruary = "févr";
|
||||||
|
window.l.fr.shortmonthsMars = "mars";
|
||||||
|
window.l.fr.shortmonthsApril = "avril";
|
||||||
|
window.l.fr.shortmonthsMay = "mai";
|
||||||
|
window.l.fr.shortmonthsJune = "juin";
|
||||||
|
window.l.fr.shortmonthsJuly = "juil";
|
||||||
|
window.l.fr.shortmonthsAugust = "août";
|
||||||
|
window.l.fr.shortmonthsSeptember = "sept";
|
||||||
|
window.l.fr.shortmonthsOctober = "oct";
|
||||||
|
window.l.fr.shortmonthsNovember = "nov";
|
||||||
|
window.l.fr.shortmonthsDecember = "déc";
|
||||||
|
window.l.fr.time12am = '{time} AM';
|
||||||
|
window.l.fr.time12pm = '{time} PM';
|
||||||
|
window.l.fr.longDateFormat = '{hours} h {minutes} - {day} {month} {year}';
|
||||||
|
window.l.fr.shortDateFormatSeconds = '{seconds} s';
|
||||||
|
window.l.fr.shortDateFormatMinutes = '{minutes} min';
|
||||||
|
window.l.fr.shortDateFormatHours = '{hours} h';
|
||||||
|
window.l.fr.shortDateFormatDate = '{day} {month}';
|
||||||
|
window.l.fr.shortDateFormatDateAndY = '{day} {month} {year}';
|
||||||
|
window.l.fr.now = 'en ce moment';
|
||||||
|
window.l.fr.posting = 'envoie';
|
||||||
|
window.l.fr.viewMoreInConvBefore = '← Voir davantage dans la conversation';
|
||||||
|
window.l.fr.viewMoreInConvAfter = 'Voir davantage dans la conversation →';
|
||||||
|
window.l.fr.mentions = 'Mentions';
|
||||||
|
window.l.fr.publicTimeline = 'Tous les queets';
|
||||||
|
window.l.fr.searchVerb = 'Rechercher';
|
||||||
|
window.l.fr.deleteVerb = 'Supprimer';
|
||||||
|
window.l.fr.cancelVerb = 'Annuler';
|
||||||
|
window.l.fr.deleteConfirmation = 'Êtes-vous sûr de vouloir supprimer ce queet ?';
|
||||||
|
window.l.fr.userFollow = 'Suivre';
|
||||||
|
window.l.fr.userFollowing = 'Abonné';
|
||||||
|
window.l.fr.userUnfollow = 'Se désabonner';
|
||||||
|
window.l.fr.joinGroup = 'Rejoindre ce groupe';
|
||||||
|
window.l.fr.isMemberOfGroup = 'Quitter le groupe';
|
||||||
|
window.l.fr.leaveGroup = 'Quitter le groupe';
|
||||||
|
window.l.fr.memberCount = 'Membres';
|
||||||
|
window.l.fr.adminCount = 'Administrateurs';
|
||||||
|
|
||||||
|
|
||||||
|
// deutsch
|
||||||
|
window.l.de = new Object();
|
||||||
|
window.l.de.languageName = 'Deutsch';
|
||||||
|
window.l.de.loginUsername = 'Benutzername oder E-Mail';
|
||||||
|
window.l.de.loginPassword = 'Passwort';
|
||||||
|
window.l.de.loginSignIn = 'Anmelden';
|
||||||
|
window.l.de.loginRememberMe = 'Angemeldet bleiben';
|
||||||
|
window.l.de.loginForgotPassword = 'Passwort vergessen?';
|
||||||
|
window.l.de.notices = 'Queets';
|
||||||
|
window.l.de.followers = 'Follower';
|
||||||
|
window.l.de.following = 'Folgt';
|
||||||
|
window.l.de.groups = 'Gruppen';
|
||||||
|
window.l.de.compose = 'Verfasse einen neuen Queet...';
|
||||||
|
window.l.de.queetVerb = 'Quittern';
|
||||||
|
window.l.de.queetsNounPlural = 'Queets';
|
||||||
|
window.l.de.logout = 'Abmelden';
|
||||||
|
window.l.de.languageSelected = 'Sprache:';
|
||||||
|
window.l.de.viewMyProfilePage = 'Mein Profil ansehen';
|
||||||
|
window.l.de.expand = 'Öffnen';
|
||||||
|
window.l.de.collapse = 'Schließen';
|
||||||
|
window.l.de.details = 'Details';
|
||||||
|
window.l.de.expandFullConversation = 'Vollständige Gespräch';
|
||||||
|
window.l.de.replyVerb = 'Antworten';
|
||||||
|
window.l.de.requeetVerb = 'Requeeten';
|
||||||
|
window.l.de.favoriteVerb = 'Favorisieren';
|
||||||
|
window.l.de.requeetedVerb = 'Requeetet';
|
||||||
|
window.l.de.favoritedVerb = 'Favorisiert';
|
||||||
|
window.l.de.replyTo = 'Antwort an';
|
||||||
|
window.l.de.requeetedBy = 'Requeetet von';
|
||||||
|
window.l.de.favoriteNoun = 'Favorisieren';
|
||||||
|
window.l.de.favoritesNoun = 'Favoriten';
|
||||||
|
window.l.de.requeetNoun = 'Requeet';
|
||||||
|
window.l.de.requeetsNoun = 'Requeets';
|
||||||
|
window.l.de.newQueet = 'neuer Queet';
|
||||||
|
window.l.de.newQueets = 'neue Queets';
|
||||||
|
window.l.de.longmonthsJanuary = "Januar";
|
||||||
|
window.l.de.longmonthsFebruary = "Februar";
|
||||||
|
window.l.de.longmonthsMars = "März";
|
||||||
|
window.l.de.longmonthsApril = "April";
|
||||||
|
window.l.de.longmonthsMay = "Mai";
|
||||||
|
window.l.de.longmonthsJune = "Juni";
|
||||||
|
window.l.de.longmonthsJuly = "Juli";
|
||||||
|
window.l.de.longmonthsAugust = "August";
|
||||||
|
window.l.de.longmonthsSeptember = "September";
|
||||||
|
window.l.de.longmonthsOctober = "Oktober";
|
||||||
|
window.l.de.longmonthsNovember = "November";
|
||||||
|
window.l.de.longmonthsDecember = "Dezember";
|
||||||
|
window.l.de.shortmonthsJanuary = "Jan";
|
||||||
|
window.l.de.shortmonthsFebruary = "Feb";
|
||||||
|
window.l.de.shortmonthsMars = "Mär";
|
||||||
|
window.l.de.shortmonthsApril = "Apr";
|
||||||
|
window.l.de.shortmonthsMay = "Mai";
|
||||||
|
window.l.de.shortmonthsJune = "Jun";
|
||||||
|
window.l.de.shortmonthsJuly = "Jul";
|
||||||
|
window.l.de.shortmonthsAugust = "Aug";
|
||||||
|
window.l.de.shortmonthsSeptember = "Sep";
|
||||||
|
window.l.de.shortmonthsOctober = "Okt";
|
||||||
|
window.l.de.shortmonthsNovember = "Nov";
|
||||||
|
window.l.de.shortmonthsDecember = "Dez";
|
||||||
|
window.l.de.time12am = '{time} AM';
|
||||||
|
window.l.de.time12pm = '{time} PM';
|
||||||
|
window.l.de.longDateFormat = '{time24} - {day} {month} {year}';
|
||||||
|
window.l.de.shortDateFormatSeconds = '{seconds}s';
|
||||||
|
window.l.de.shortDateFormatMinutes = '{minutes}m';
|
||||||
|
window.l.de.shortDateFormatHours = '{hours}h';
|
||||||
|
window.l.de.shortDateFormatDate = '{day}{month}';
|
||||||
|
window.l.de.shortDateFormatDateAndY = '{day}{month} {year}';
|
||||||
|
window.l.de.now = 'jetzt';
|
||||||
|
window.l.de.posting = 'Entsendung';
|
||||||
|
window.l.de.viewMoreInConvBefore = '← Mehr im Gespräch anzeigen';
|
||||||
|
window.l.de.viewMoreInConvAfter = 'Mehr im Gespräch anzeigen →';
|
||||||
|
window.l.de.mentions = 'Erwähnungen';
|
||||||
|
window.l.de.publicTimeline = 'Öffentliche Zeitleiste';
|
||||||
|
window.l.de.searchVerb = 'Suche';
|
||||||
|
window.l.de.deleteVerb = 'Löschen';
|
||||||
|
window.l.de.cancelVerb = 'Abbrechen';
|
||||||
|
window.l.de.deleteConfirmation = 'Bist Du sicher, dass Du diesen Queet löschen möchtest?';
|
||||||
|
window.l.de.userFollow = 'Folgen';
|
||||||
|
window.l.de.userFollowing = 'Folge ich';
|
||||||
|
window.l.de.userUnfollow = 'Entfolgen';
|
||||||
|
window.l.de.joinGroup = 'Der Gruppe beitreten';
|
||||||
|
window.l.de.isMemberOfGroup = 'Gruppe verlassen';
|
||||||
|
window.l.de.leaveGroup = 'Gruppe verlassen';
|
||||||
|
window.l.de.memberCount = 'Mitglieder';
|
||||||
|
window.l.de.adminCount = 'Administratoren';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// english
|
||||||
|
window.l.en = new Object();
|
||||||
|
window.l.en.languageName = 'English';
|
||||||
|
window.l.en.loginUsername = 'Username or e-mail';
|
||||||
|
window.l.en.loginPassword = 'Password';
|
||||||
|
window.l.en.loginSignIn = 'Sign in';
|
||||||
|
window.l.en.loginRememberMe = 'Remember me';
|
||||||
|
window.l.en.loginForgotPassword = 'Forgot password?';
|
||||||
|
window.l.en.notices = 'Queets';
|
||||||
|
window.l.en.followers = 'Followers';
|
||||||
|
window.l.en.following = 'Following';
|
||||||
|
window.l.en.groups = 'Groups';
|
||||||
|
window.l.en.compose = 'Compose new Queet...';
|
||||||
|
window.l.en.queetVerb = 'Queet';
|
||||||
|
window.l.en.queetsNounPlural = 'Queets';
|
||||||
|
window.l.en.logout = 'Sign out';
|
||||||
|
window.l.en.languageSelected = 'Language:';
|
||||||
|
window.l.en.viewMyProfilePage = 'View my profile page';
|
||||||
|
window.l.en.expand = 'Expand';
|
||||||
|
window.l.en.collapse = 'Collapse';
|
||||||
|
window.l.en.details = 'Details';
|
||||||
|
window.l.en.expandFullConversation = 'Expand full conversation';
|
||||||
|
window.l.en.replyVerb = 'Reply';
|
||||||
|
window.l.en.requeetVerb = 'Requeet';
|
||||||
|
window.l.en.favoriteVerb = 'Favorite';
|
||||||
|
window.l.en.requeetedVerb = 'Requeeted';
|
||||||
|
window.l.en.favoritedVerb = 'Favorited';
|
||||||
|
window.l.en.replyTo = 'Reply to';
|
||||||
|
window.l.en.requeetedBy = 'Requeeted by';
|
||||||
|
window.l.en.favoriteNoun = 'Favorite';
|
||||||
|
window.l.en.favoritesNoun = 'Favorites';
|
||||||
|
window.l.en.requeetNoun = 'Requeet';
|
||||||
|
window.l.en.requeetsNoun = 'Requeets';
|
||||||
|
window.l.en.newQueet = 'new Queet';
|
||||||
|
window.l.en.newQueets = 'new Queets';
|
||||||
|
window.l.en.longmonthsJanuary = "January";
|
||||||
|
window.l.en.longmonthsFebruary = "February";
|
||||||
|
window.l.en.longmonthsMars = "Mars";
|
||||||
|
window.l.en.longmonthsApril = "April";
|
||||||
|
window.l.en.longmonthsMay = "May";
|
||||||
|
window.l.en.longmonthsJune = "June";
|
||||||
|
window.l.en.longmonthsJuly = "July";
|
||||||
|
window.l.en.longmonthsAugust = "August";
|
||||||
|
window.l.en.longmonthsSeptember = "September";
|
||||||
|
window.l.en.longmonthsOctober = "October";
|
||||||
|
window.l.en.longmonthsNovember = "November";
|
||||||
|
window.l.en.longmonthsDecember = "December";
|
||||||
|
window.l.en.shortmonthsJanuary = "jan";
|
||||||
|
window.l.en.shortmonthsFebruary = "feb";
|
||||||
|
window.l.en.shortmonthsMars = "mar";
|
||||||
|
window.l.en.shortmonthsApril = "apr";
|
||||||
|
window.l.en.shortmonthsMay = "may";
|
||||||
|
window.l.en.shortmonthsJune = "jun";
|
||||||
|
window.l.en.shortmonthsJuly = "jul";
|
||||||
|
window.l.en.shortmonthsAugust = "aug";
|
||||||
|
window.l.en.shortmonthsSeptember = "sep";
|
||||||
|
window.l.en.shortmonthsOctober = "oct";
|
||||||
|
window.l.en.shortmonthsNovember = "nov";
|
||||||
|
window.l.en.shortmonthsDecember = "dec";
|
||||||
|
window.l.en.time12am = '{time} am';
|
||||||
|
window.l.en.time12pm = '{time} pm';
|
||||||
|
window.l.en.longDateFormat = '{time12} - {day} {month} {year}';
|
||||||
|
window.l.en.shortDateFormatSeconds = '{seconds}s';
|
||||||
|
window.l.en.shortDateFormatMinutes = '{minutes}m';
|
||||||
|
window.l.en.shortDateFormatHours = '{hours}h';
|
||||||
|
window.l.en.shortDateFormatDate = '{day} {month}';
|
||||||
|
window.l.en.shortDateFormatDateAndY = '{day} {month} {year}';
|
||||||
|
window.l.en.now = 'now';
|
||||||
|
window.l.en.posting = 'posting';
|
||||||
|
window.l.en.viewMoreInConvBefore = '← View more in conversation';
|
||||||
|
window.l.en.viewMoreInConvAfter = 'View more in conversation →';
|
||||||
|
window.l.en.mentions = 'Mentions';
|
||||||
|
window.l.en.publicTimeline = 'Public Timeline';
|
||||||
|
window.l.en.searchVerb = 'Search';
|
||||||
|
window.l.en.deleteVerb = 'Delete';
|
||||||
|
window.l.en.cancelVerb = 'Cancel';
|
||||||
|
window.l.en.deleteConfirmation = 'Are you sure you want to delete this queet?';
|
||||||
|
window.l.en.userFollow = 'Follow';
|
||||||
|
window.l.en.userFollowing = 'Following';
|
||||||
|
window.l.en.userUnfollow = 'Unfollow';
|
||||||
|
window.l.en.joinGroup = 'Join';
|
||||||
|
window.l.en.isMemberOfGroup = 'Member';
|
||||||
|
window.l.en.leaveGroup = 'Leave';
|
||||||
|
window.l.en.memberCount = 'Members';
|
||||||
|
window.l.en.adminCount = 'Admins';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// svenska
|
||||||
|
window.l.sv = new Object();
|
||||||
|
window.l.sv.languageName = 'Svenska';
|
||||||
|
window.l.sv.loginUsername = 'Användarnamn eller mejladress';
|
||||||
|
window.l.sv.loginPassword = 'Lösenord';
|
||||||
|
window.l.sv.loginSignIn = 'Logga in';
|
||||||
|
window.l.sv.loginRememberMe = 'Kom ihåg mig';
|
||||||
|
window.l.sv.loginForgotPassword = 'Glömt lösenordet?';
|
||||||
|
window.l.sv.notices = 'Qvittrat';
|
||||||
|
window.l.sv.followers = 'Följare';
|
||||||
|
window.l.sv.following = 'Följer';
|
||||||
|
window.l.sv.groups = 'Grupper';
|
||||||
|
window.l.sv.compose = 'Skriv nytt qvitter';
|
||||||
|
window.l.sv.queetVerb = 'Qvittra';
|
||||||
|
window.l.sv.queetsNounPlural = 'Qvitter';
|
||||||
|
window.l.sv.logout = 'Logga ut';
|
||||||
|
window.l.sv.languageSelected = 'Språk:';
|
||||||
|
window.l.sv.viewMyProfilePage = 'Visa min profilsida';
|
||||||
|
window.l.sv.expand = 'Visa';
|
||||||
|
window.l.sv.collapse = 'Stäng';
|
||||||
|
window.l.sv.details = 'Detaljer';
|
||||||
|
window.l.sv.expandFullConversation = 'Visa hela konversationen';
|
||||||
|
window.l.sv.replyVerb = 'Svara';
|
||||||
|
window.l.sv.requeetVerb = 'Requeeta';
|
||||||
|
window.l.sv.favoriteVerb = 'Favoritmarkera';
|
||||||
|
window.l.sv.requeetedVerb = 'Requeetad';
|
||||||
|
window.l.sv.favoritedVerb = 'Favoritmarkerad';
|
||||||
|
window.l.sv.replyTo = 'Svara';
|
||||||
|
window.l.sv.requeetedBy = 'requeetad av';
|
||||||
|
window.l.sv.favoriteNoun = 'favorit';
|
||||||
|
window.l.sv.favoritesNoun = 'Favoriter';
|
||||||
|
window.l.sv.requeetNoun = 'requeet';
|
||||||
|
window.l.sv.requeetsNoun = 'requeets';
|
||||||
|
window.l.sv.newQueet = 'nytt qvitter';
|
||||||
|
window.l.sv.newQueets = 'nya qvitter';
|
||||||
|
window.l.sv.longmonthsJanuary = "januari";
|
||||||
|
window.l.sv.longmonthsFebruary = "februari";
|
||||||
|
window.l.sv.longmonthsMars = "mars";
|
||||||
|
window.l.sv.longmonthsApril = "april";
|
||||||
|
window.l.sv.longmonthsMay = "maj";
|
||||||
|
window.l.sv.longmonthsJune = "juni";
|
||||||
|
window.l.sv.longmonthsJuly = "juli";
|
||||||
|
window.l.sv.longmonthsAugust = "augusti";
|
||||||
|
window.l.sv.longmonthsSeptember = "september";
|
||||||
|
window.l.sv.longmonthsOctober = "oktober";
|
||||||
|
window.l.sv.longmonthsNovember = "november";
|
||||||
|
window.l.sv.longmonthsDecember = "december";
|
||||||
|
window.l.sv.shortmonthsJanuary = "jan";
|
||||||
|
window.l.sv.shortmonthsFebruary = "feb";
|
||||||
|
window.l.sv.shortmonthsMars = "mar";
|
||||||
|
window.l.sv.shortmonthsApril = "apr";
|
||||||
|
window.l.sv.shortmonthsMay = "maj";
|
||||||
|
window.l.sv.shortmonthsJune = "jun";
|
||||||
|
window.l.sv.shortmonthsJuly = "jul";
|
||||||
|
window.l.sv.shortmonthsAugust = "aug";
|
||||||
|
window.l.sv.shortmonthsSeptember = "sep";
|
||||||
|
window.l.sv.shortmonthsOctober = "okt";
|
||||||
|
window.l.sv.shortmonthsNovember = "nov";
|
||||||
|
window.l.sv.shortmonthsDecember = "dec";
|
||||||
|
window.l.sv.time12am = '{time} f.m.';
|
||||||
|
window.l.sv.time12pm = '{time} e.m.';
|
||||||
|
window.l.sv.longDateFormat = '{time24} - {day} {month} {year}';
|
||||||
|
window.l.sv.shortDateFormatSeconds = '{seconds}s';
|
||||||
|
window.l.sv.shortDateFormatMinutes = '{minutes}m';
|
||||||
|
window.l.sv.shortDateFormatHours = '{hours}h';
|
||||||
|
window.l.sv.shortDateFormatDate = '{day} {month}';
|
||||||
|
window.l.sv.shortDateFormatDateAndY = '{day} {month} {year}';
|
||||||
|
window.l.sv.now = 'nyss';
|
||||||
|
window.l.sv.posting = 'postar';
|
||||||
|
window.l.sv.viewMoreInConvBefore = '← Visa mer i konversationen';
|
||||||
|
window.l.sv.viewMoreInConvAfter = 'Visa mer i konversationen →';
|
||||||
|
window.l.sv.mentions = 'Omnämnanden';
|
||||||
|
window.l.sv.publicTimeline = 'Hela sajtens flöde';
|
||||||
|
window.l.sv.searchVerb = 'Sök';
|
||||||
|
window.l.sv.deleteVerb = 'Ta bort';
|
||||||
|
window.l.sv.cancelVerb = 'Avbryt';
|
||||||
|
window.l.sv.deleteConfirmation = 'Är du säker på att du vill radera denna queet?';
|
||||||
|
window.l.sv.userFollow = 'Följ';
|
||||||
|
window.l.sv.userFollowing = 'Följer';
|
||||||
|
window.l.sv.userUnfollow = 'Avfölj';
|
||||||
|
window.l.sv.joinGroup = 'Gå med';
|
||||||
|
window.l.sv.isMemberOfGroup = 'Medlem';
|
||||||
|
window.l.sv.leaveGroup = 'Gå ur';
|
||||||
|
window.l.sv.memberCount = 'Medlemmar';
|
||||||
|
window.l.sv.adminCount = 'Administratörer';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// farsi/persian
|
||||||
|
window.l.fa = new Object();
|
||||||
|
window.l.fa.languageName = 'فارسی';
|
||||||
|
window.l.fa.loginUsername = 'شناسه یا ایمیل';
|
||||||
|
window.l.fa.loginPassword = 'گذرواژه - رمز عبور';
|
||||||
|
window.l.fa.loginSignIn = 'ورود';
|
||||||
|
window.l.fa.loginRememberMe = 'مرا به یاد داشته باش';
|
||||||
|
window.l.fa.loginForgotPassword = 'گذرواژه خود را فراموش کردهاید؟';
|
||||||
|
window.l.fa.notices = 'توییت';
|
||||||
|
window.l.fa.followers = 'دنبالکننده';
|
||||||
|
window.l.fa.following = 'دنبالشونده';
|
||||||
|
window.l.fa.groups = 'گروه';
|
||||||
|
window.l.fa.compose = 'نوشتن یک توییت تازه...';
|
||||||
|
window.l.fa.queetVerb = 'توییت';
|
||||||
|
window.l.fa.queetsNounPlural = 'توييتها';
|
||||||
|
window.l.fa.logout = 'خروج';
|
||||||
|
window.l.fa.languageSelected = 'زبان:';
|
||||||
|
window.l.fa.viewMyProfilePage = 'دیدن صفحه نمایه';
|
||||||
|
window.l.fa.expand = 'گستردن';
|
||||||
|
window.l.fa.collapse = 'بستن';
|
||||||
|
window.l.fa.details = 'جزئیات';
|
||||||
|
window.l.fa.expandFullConversation = 'نمایش مکالمه کامل';
|
||||||
|
window.l.fa.replyVerb = 'پاسخ';
|
||||||
|
window.l.fa.requeetVerb = 'بازتوییت';
|
||||||
|
window.l.fa.favoriteVerb = 'برگزیدن';
|
||||||
|
window.l.fa.requeetedVerb = 'بازتوییت شده';
|
||||||
|
window.l.fa.favoritedVerb = 'برگزیده شده';
|
||||||
|
window.l.fa.replyTo = 'پاسخ به';
|
||||||
|
window.l.fa.requeetedBy = 'بازتوییت شده توسط';
|
||||||
|
window.l.fa.favoriteNoun = 'برگزیده';
|
||||||
|
window.l.fa.favoritesNoun = 'برگزیده';
|
||||||
|
window.l.fa.requeetNoun = 'بازتوییت';
|
||||||
|
window.l.fa.requeetsNoun = 'بازتوییت';
|
||||||
|
window.l.fa.newQueet = 'توییت جدید';
|
||||||
|
window.l.fa.newQueets = 'توییت جدید';
|
||||||
|
window.l.fa.longmonthsJanuary = "ژانويه";
|
||||||
|
window.l.fa.longmonthsFebruary = "فوريه";
|
||||||
|
window.l.fa.longmonthsMars = "مارس";
|
||||||
|
window.l.fa.longmonthsApril = "اوريل";
|
||||||
|
window.l.fa.longmonthsMay = "مه";
|
||||||
|
window.l.fa.longmonthsJune = "ژوءن";
|
||||||
|
window.l.fa.longmonthsJuly = "ژوءيه";
|
||||||
|
window.l.fa.longmonthsAugust = "اوت";
|
||||||
|
window.l.fa.longmonthsSeptember = "سپتامبر";
|
||||||
|
window.l.fa.longmonthsOctober = "اكتبر";
|
||||||
|
window.l.fa.longmonthsNovember = "نوامبر";
|
||||||
|
window.l.fa.longmonthsDecember = "دسامبر";
|
||||||
|
window.l.fa.shortmonthsJanuary = "ژانويه";
|
||||||
|
window.l.fa.shortmonthsFebruary = "فوريه";
|
||||||
|
window.l.fa.shortmonthsMars = "مارس";
|
||||||
|
window.l.fa.shortmonthsApril = "اوريل";
|
||||||
|
window.l.fa.shortmonthsMay = "مه";
|
||||||
|
window.l.fa.shortmonthsJune = "ژوءن";
|
||||||
|
window.l.fa.shortmonthsJuly = "ژوءيه";
|
||||||
|
window.l.fa.shortmonthsAugust = "اوت";
|
||||||
|
window.l.fa.shortmonthsSeptember = "سپتامبر";
|
||||||
|
window.l.fa.shortmonthsOctober = "اكتبر";
|
||||||
|
window.l.fa.shortmonthsNovember = "نوامبر";
|
||||||
|
window.l.fa.shortmonthsDecember = "دسامبر";
|
||||||
|
window.l.fa.time12am = '{time} am';
|
||||||
|
window.l.fa.time12pm = '{time} pm';
|
||||||
|
window.l.fa.longDateFormat = '{time24} - {day} {month} {year}';
|
||||||
|
window.l.fa.shortDateFormatSeconds = '{seconds} ثانیه';
|
||||||
|
window.l.fa.shortDateFormatMinutes = '{minutes} دقیقه';
|
||||||
|
window.l.fa.shortDateFormatHours = '{hours} ساعت';
|
||||||
|
window.l.fa.shortDateFormatDate = '{day} {month}';
|
||||||
|
window.l.fa.shortDateFormatDateAndY = '{day} {month} {year}';
|
||||||
|
window.l.fa.now = 'فقط در حال حاضر';
|
||||||
|
window.l.fa.posting = 'می فرستد';
|
||||||
|
window.l.fa.viewMoreInConvBefore = '→ نمایش بیشتر در گفتگوها';
|
||||||
|
window.l.fa.viewMoreInConvAfter = 'نمایش بیشتر در گفتگوها ←';
|
||||||
|
window.l.fa.mentions = 'رونوشتها';
|
||||||
|
window.l.fa.publicTimeline = 'خطزمانی عمومی';
|
||||||
|
window.l.fa.searchVerb = 'جستجو';
|
||||||
|
window.l.fa.deleteVerb = 'حذف';
|
||||||
|
window.l.fa.cancelVerb = 'لغو';
|
||||||
|
window.l.fa.deleteConfirmation = 'آیا مطمئن هستید که میخواهید این توییت را پاک کنید؟';
|
||||||
|
window.l.fa.userFollow = 'دنبال کنید';
|
||||||
|
window.l.fa.userFollowing = 'دنبال میکنید';
|
||||||
|
window.l.fa.userUnfollow = 'دنبال نكن';
|
||||||
|
window.l.fa.joinGroup = 'پیوستن به گروه';
|
||||||
|
window.l.fa.isMemberOfGroup = 'ترک گروه';
|
||||||
|
window.l.fa.leaveGroup = 'ترک گروه';
|
||||||
|
window.l.fa.memberCount = 'اعضای';
|
||||||
|
window.l.fa.adminCount = 'مدیران';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// arabic
|
||||||
|
window.l.ar = new Object();
|
||||||
|
window.l.ar.languageName = 'العربيّة';
|
||||||
|
window.l.ar.loginUsername = 'اسم المستخدم أو البريد الإلكترونيّ';
|
||||||
|
window.l.ar.loginPassword = 'كلمة المرور';
|
||||||
|
window.l.ar.loginSignIn = 'تسجيل الدخول';
|
||||||
|
window.l.ar.loginRememberMe = 'تذكّرني';
|
||||||
|
window.l.ar.loginForgotPassword = 'نسيت كلمة المرور؟';
|
||||||
|
window.l.ar.notices = 'تغريدات';
|
||||||
|
window.l.ar.followers = 'متابِعين';
|
||||||
|
window.l.ar.following = 'متابَعين';
|
||||||
|
window.l.ar.groups = 'جماعة';
|
||||||
|
window.l.ar.compose = 'اكتب تغريدة جديدة...';
|
||||||
|
window.l.ar.queetVerb = 'تغريد';
|
||||||
|
window.l.ar.queetsNounPlural = 'تغريدات';
|
||||||
|
window.l.ar.logout = 'تسجيل الخروج';
|
||||||
|
window.l.ar.languageSelected = 'اللغة:';
|
||||||
|
window.l.ar.viewMyProfilePage = 'عرض صفحة ملفي الشخصي';
|
||||||
|
window.l.ar.expand = 'فتح';
|
||||||
|
window.l.ar.collapse = 'إغلاق';
|
||||||
|
window.l.ar.details = 'التفاصيل';
|
||||||
|
window.l.ar.expandFullConversation = 'مشاهدة المحادثة';
|
||||||
|
window.l.ar.replyVerb = 'رَد';
|
||||||
|
window.l.ar.requeetVerb = 'إعادة تغريد';
|
||||||
|
window.l.ar.favoriteVerb = 'تفضيل';
|
||||||
|
window.l.ar.requeetedVerb = 'مُعاد تغريدها';
|
||||||
|
window.l.ar.favoritedVerb = 'مُفضّلة';
|
||||||
|
window.l.ar.replyTo = 'أرسِل ردًا إلى';
|
||||||
|
window.l.ar.requeetedBy = 'مُعاد تغريدها بواسطة';
|
||||||
|
window.l.ar.favoriteNoun = 'مفضّلة';
|
||||||
|
window.l.ar.favoritesNoun = 'مفضّلة';
|
||||||
|
window.l.ar.requeetNoun = 'إعادة تغريد';
|
||||||
|
window.l.ar.requeetsNoun = 'إعادة تغريد';
|
||||||
|
window.l.ar.newQueet = 'تغريدة جديدة';
|
||||||
|
window.l.ar.newQueets = 'تغريدة جديدة';
|
||||||
|
window.l.ar.longmonthsJanuary = "يناير";
|
||||||
|
window.l.ar.longmonthsFebruary = "فبراير";
|
||||||
|
window.l.ar.longmonthsMars = "مارس";
|
||||||
|
window.l.ar.longmonthsApril = "أبريل";
|
||||||
|
window.l.ar.longmonthsMay = "مايو";
|
||||||
|
window.l.ar.longmonthsJune = "يونيو";
|
||||||
|
window.l.ar.longmonthsJuly = "يوليو";
|
||||||
|
window.l.ar.longmonthsAugust = "أغسطس";
|
||||||
|
window.l.ar.longmonthsSeptember = "سبتمبر";
|
||||||
|
window.l.ar.longmonthsOctober = "أكتوبر";
|
||||||
|
window.l.ar.longmonthsNovember = "نوفمبر";
|
||||||
|
window.l.ar.longmonthsDecember = "ديسمبر";
|
||||||
|
window.l.ar.shortmonthsJanuary = "يناير";
|
||||||
|
window.l.ar.shortmonthsFebruary = "فبراير";
|
||||||
|
window.l.ar.shortmonthsMars = "مارس";
|
||||||
|
window.l.ar.shortmonthsApril = "أبريل";
|
||||||
|
window.l.ar.shortmonthsMay = "مايو";
|
||||||
|
window.l.ar.shortmonthsJune = "يونيو";
|
||||||
|
window.l.ar.shortmonthsJuly = "يوليو";
|
||||||
|
window.l.ar.shortmonthsAugust = "أغسطس";
|
||||||
|
window.l.ar.shortmonthsSeptember = "سبتمبر";
|
||||||
|
window.l.ar.shortmonthsOctober = "أكتوبر";
|
||||||
|
window.l.ar.shortmonthsNovember = "نوفمبر";
|
||||||
|
window.l.ar.shortmonthsDecember = "ديسمبر";
|
||||||
|
window.l.ar.time12am = '{time} صباحًا';
|
||||||
|
window.l.ar.time12pm = '{time} مساءً';
|
||||||
|
window.l.ar.longDateFormat = '{time12} - {day} {month} {year}';
|
||||||
|
window.l.ar.shortDateFormatSeconds = '{seconds} ث';
|
||||||
|
window.l.ar.shortDateFormatMinutes = '{minutes} د';
|
||||||
|
window.l.ar.shortDateFormatHours = '{hours} س';
|
||||||
|
window.l.ar.shortDateFormatDate = '{day} {month}';
|
||||||
|
window.l.ar.shortDateFormatDateAndY = '{day} {month} {year}';
|
||||||
|
window.l.ar.now = 'الآن';
|
||||||
|
window.l.ar.posting = 'إرسال';
|
||||||
|
window.l.ar.viewMoreInConvBefore = '→ عرض المزيد في المحادثة';
|
||||||
|
window.l.ar.viewMoreInConvAfter = 'عرض المزيد في المحادثة ←';
|
||||||
|
window.l.ar.mentions = 'الإشارات';
|
||||||
|
window.l.ar.publicTimeline = 'المسار الزمني العام';
|
||||||
|
window.l.ar.searchVerb = 'بحث';
|
||||||
|
window.l.ar.deleteVerb = 'حذف';
|
||||||
|
window.l.ar.cancelVerb = 'إلغاء';
|
||||||
|
window.l.ar.deleteConfirmation = 'هل أنت متأكد أنك تريد حذف هذه التغريدة؟';
|
||||||
|
window.l.ar.userFollow = 'تابِع';
|
||||||
|
window.l.ar.userFollowing = 'مُتابَع';
|
||||||
|
window.l.ar.userUnfollow = 'إلغاء المتابعة';
|
||||||
|
window.l.ar.joinGroup = 'الانضمام إلى المجموعة';
|
||||||
|
window.l.ar.isMemberOfGroup = 'مغادرة المجموعة';
|
||||||
|
window.l.ar.leaveGroup = 'مغادرة المجموعة';
|
||||||
|
window.l.ar.memberCount = 'الأعضاء';
|
||||||
|
window.l.ar.adminCount = 'الإداريين';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// set language, from local storage, else browser language, else english
|
||||||
|
var browserLang = navigator.language || navigator.userLanguage;
|
||||||
|
var selectedLanguage = 'en';
|
||||||
|
if(typeof localStorage.selectedLanguage != 'undefined') {
|
||||||
|
selectedLanguage = localStorage.selectedLanguage;
|
||||||
|
}
|
||||||
|
else if(typeof window.l[browserLang.substring(0,2)] != 'undefined') {
|
||||||
|
selectedLanguage = browserLang.substring(0,2);
|
||||||
|
}
|
||||||
|
window.sL = window.l[selectedLanguage];
|
||||||
|
|
||||||
|
// if this is a RTL-language, add rt classes and change some things
|
||||||
|
if(selectedLanguage == 'ar') {
|
||||||
|
$('body').addClass('rtl');
|
||||||
|
$('#birds-top').attr('src',window.fullUrlToThisQvitterApp + 'img/birds_rtl.png');
|
||||||
|
$('title').html('‫ترك');
|
||||||
|
}
|
||||||
|
else if(selectedLanguage == 'fa') {
|
||||||
|
$('body').addClass('rtl');
|
||||||
|
$('#birds-top').attr('src', window.fullUrlToThisQvitterApp + 'img/birds_rtl.png');
|
||||||
|
$('title').html('‫واگذارنده');
|
||||||
|
}
|
||||||
|
|
||||||
|
window.siteTitle = $('head title').html(); // remember this for later use
|
||||||
|
|
||||||
|
// set some static string
|
||||||
|
$('#username').attr('placeholder',window.sL.loginUsername);
|
||||||
|
$('#password').attr('placeholder',window.sL.loginPassword);
|
||||||
|
$('button#submit-login').html(window.sL.loginSignIn);
|
||||||
|
$('#rememberme_label').html(window.sL.loginRememberMe);
|
||||||
|
$('#remember-forgot a').html(window.sL.loginForgotPassword);
|
||||||
|
$('#user-queets .label').html(window.sL.notices);
|
||||||
|
$('#user-following .label').html(window.sL.following);
|
||||||
|
$('#user-followers .label').html(window.sL.followers);
|
||||||
|
$('#user-groups .label').html(window.sL.groups);
|
||||||
|
$('#queet-box').html(window.sL.compose);
|
||||||
|
$('#queet').html(window.sL.queetVerb);
|
||||||
|
$('#feed-header-inner h2').html(window.sL.queetsNounPlural);
|
||||||
|
$('#logout').html(window.sL.logout);
|
||||||
|
$('.language-dropdown .dropdown-toggle small').html(window.sL.languageSelected);
|
||||||
|
$('.language-dropdown .current-language').html(window.sL.languageName);
|
||||||
|
$('.stream-selection[data-stream-name="statuses/friends_timeline.json"]').prepend(window.sL.queetsNounPlural);
|
||||||
|
$('.stream-selection[data-stream-name="statuses/friends_timeline.json"]').attr('data-stream-header',window.sL.queetsNounPlural);
|
||||||
|
$('.stream-selection[data-stream-name="statuses/mentions.json"]').prepend(window.sL.mentions);
|
||||||
|
$('.stream-selection[data-stream-name="statuses/mentions.json"]').attr('data-stream-header',window.sL.mentions);
|
||||||
|
$('.stream-selection[data-stream-name="favorites.json"]').prepend(window.sL.favoritesNoun);
|
||||||
|
$('.stream-selection[data-stream-name="favorites.json"]').attr('data-stream-header',window.sL.favoritesNoun);
|
||||||
|
$('.stream-selection[data-stream-name="statuses/public_timeline.json"]').prepend(window.sL.publicTimeline);
|
||||||
|
$('.stream-selection[data-stream-name="statuses/public_timeline.json"]').attr('data-stream-header',window.sL.publicTimeline);
|
||||||
|
$('#search-query').attr('placeholder',window.sL.searchVerb);
|
401
js/misc-functions-1.js
Normal file
|
@ -0,0 +1,401 @@
|
||||||
|
|
||||||
|
/* · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· Q V I T T E R ·
|
||||||
|
· ·
|
||||||
|
· http://github.com/hannesmannerheim/qvitter ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· <o) ·
|
||||||
|
· /_//// ·
|
||||||
|
· (____/ ·
|
||||||
|
· (o< ·
|
||||||
|
· o> \\\\_\ ·
|
||||||
|
· \\) \____) ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· Qvitter is free software: you can redistribute it and / or modify it ·
|
||||||
|
· under the terms of the GNU Affero General Public License as published by ·
|
||||||
|
· the Free Software Foundation, either version three of the License or (at ·
|
||||||
|
· your option) any later version. ·
|
||||||
|
· ·
|
||||||
|
· Qvitter is distributed in hope that it will be useful but WITHOUT ANY ·
|
||||||
|
· WARRANTY; without even the implied warranty of MERCHANTABILTY or FITNESS ·
|
||||||
|
· FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for ·
|
||||||
|
· more details. ·
|
||||||
|
· ·
|
||||||
|
· You should have received a copy of the GNU Affero General Public License ·
|
||||||
|
· along with Qvitter. If not, see <http://www.gnu.org/licenses/>. ·
|
||||||
|
· ·
|
||||||
|
· Contact h@nnesmannerhe.im if you have any questions. ·
|
||||||
|
· ·
|
||||||
|
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Right-to-left language detection <o
|
||||||
|
· (//
|
||||||
|
· @param s: the stream-item to detect rtl in
|
||||||
|
·
|
||||||
|
· @return a stream-item that might have rtl-class added
|
||||||
|
·
|
||||||
|
· · · · · · · · · */
|
||||||
|
|
||||||
|
function detectRTL(s) {
|
||||||
|
var $streamItem = $('<div>').append(s);
|
||||||
|
var $queetText = $('<div>').append($streamItem.find('.queet-text').html()); // create an jquery object
|
||||||
|
var $a = $queetText.find('a'); $a.remove(); // remove links
|
||||||
|
var $vcard = $queetText.find('.vcard'); $vcard.remove(); // remove users, groups
|
||||||
|
var $tag = $queetText.find('.tag'); $tag.remove(); // remove tags
|
||||||
|
if($queetText.find('.rtl').length>0) { $queetText.html($queetText.find('.rtl').html()); } // remove rtl container if there is one
|
||||||
|
// remove chars we're not interested in
|
||||||
|
$queetText.html($queetText.html().replace(/\@/gi,'').replace(/\#/gi,'').replace(/\!/gi,'').replace(/\(/gi,'').replace(/\)/gi,'').replace(/\:D/gi,'').replace(/D\:/gi,'').replace(/\:/gi,'').replace(/\-/gi,'').replace(/\s/gi, ''));
|
||||||
|
// count ltr and rtl chars
|
||||||
|
var ltrChars = 'A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF'+'\u2C00-\uFB1C\uFDFE-\uFE6F\uFEFD-\uFFFF',
|
||||||
|
rtlChars = '\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC',
|
||||||
|
rtlDirCheck = new RegExp('^[^'+ltrChars+']*['+rtlChars+']'),
|
||||||
|
RTLnum = 0,
|
||||||
|
LTRnum = 0,
|
||||||
|
RTLorLTR = $queetText.html();
|
||||||
|
for (var i = 0, len = RTLorLTR.length; i < len; i++) {
|
||||||
|
if(rtlDirCheck.test(RTLorLTR[i])) { RTLnum++; }
|
||||||
|
else { LTRnum++; }
|
||||||
|
}
|
||||||
|
// if there are more rtl chars than ltr
|
||||||
|
if(RTLnum > LTRnum) { $streamItem.children('.stream-item').children('.queet').addClass('rtl'); }
|
||||||
|
// if no chars (that we are interested, but body is set to rtl)
|
||||||
|
else if ($queetText.html().length==0 && $('body').hasClass('rtl')) {
|
||||||
|
$streamItem.children('.stream-item').children('.queet').addClass('rtl');
|
||||||
|
}
|
||||||
|
return $streamItem.html().replace(/@<span class="vcard">/gi,'<span class="vcard">').replace(/!<span class="vcard">/gi,'<span class="vcard">').replace(/#<span class="tag">/gi,'<span class="tag">'); // hacky way to get @#! into mention tags to stop bidirection (css sets an @ with before content method)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Takes twitter style dates and converts them
|
||||||
|
·
|
||||||
|
· @param tdate: date in the form of e.g. 'Mon Aug 05 16:30:22 +0200 2013'
|
||||||
|
·
|
||||||
|
· @return user friendly dates ..M_
|
||||||
|
· W
|
||||||
|
· Needs global language object window.sL to be populated
|
||||||
|
·
|
||||||
|
· · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
function parseTwitterDate(tdate) {
|
||||||
|
var month_names = new Array ();
|
||||||
|
month_names[month_names.length] = window.sL.shortmonthsJanuary;
|
||||||
|
month_names[month_names.length] = window.sL.shortmonthsFebruary
|
||||||
|
month_names[month_names.length] = window.sL.shortmonthsMars
|
||||||
|
month_names[month_names.length] = window.sL.shortmonthsApril
|
||||||
|
month_names[month_names.length] = window.sL.shortmonthsMay
|
||||||
|
month_names[month_names.length] = window.sL.shortmonthsJune
|
||||||
|
month_names[month_names.length] = window.sL.shortmonthsJuly
|
||||||
|
month_names[month_names.length] = window.sL.shortmonthsAugust
|
||||||
|
month_names[month_names.length] = window.sL.shortmonthsSeptember
|
||||||
|
month_names[month_names.length] = window.sL.shortmonthsOctober
|
||||||
|
month_names[month_names.length] = window.sL.shortmonthsNovember
|
||||||
|
month_names[month_names.length] = window.sL.shortmonthsDecember
|
||||||
|
var system_date = new Date(Date.parse(tdate));
|
||||||
|
var user_date = new Date();
|
||||||
|
var diff = Math.floor((user_date - system_date) / 1000);
|
||||||
|
if (diff <= 10) {return window.sL.now;}
|
||||||
|
if (diff < 60) {return window.sL.shortDateFormatSeconds.replace('{seconds}',Math.round(diff/10)*10);}
|
||||||
|
if (diff <= 3540) {return window.sL.shortDateFormatMinutes.replace('{minutes}',Math.round(diff / 60));}
|
||||||
|
if (diff <= 86400) {return window.sL.shortDateFormatHours.replace('{hours}',Math.round(diff / 3600));}
|
||||||
|
if (diff <= 31536000) {return window.sL.shortDateFormatDate.replace('{day}',system_date.getDate()).replace('{month}',month_names[system_date.getMonth()]);}
|
||||||
|
if (diff > 31536000) {return window.sL.shortDateFormatDateAndY.replace('{day}',system_date.getDate()).replace('{month}',month_names[system_date.getMonth()]).replace('{year}',system_date.getFullYear());}
|
||||||
|
return system_date;
|
||||||
|
}
|
||||||
|
function parseTwitterLongDate(tdate) {
|
||||||
|
var month_names = new Array ();
|
||||||
|
month_names[month_names.length] = window.sL.longmonthsJanuary;
|
||||||
|
month_names[month_names.length] = window.sL.longmonthsFebruary
|
||||||
|
month_names[month_names.length] = window.sL.longmonthsMars
|
||||||
|
month_names[month_names.length] = window.sL.longmonthsApril
|
||||||
|
month_names[month_names.length] = window.sL.longmonthsMay
|
||||||
|
month_names[month_names.length] = window.sL.longmonthsJune
|
||||||
|
month_names[month_names.length] = window.sL.longmonthsJuly
|
||||||
|
month_names[month_names.length] = window.sL.longmonthsAugust
|
||||||
|
month_names[month_names.length] = window.sL.longmonthsSeptember
|
||||||
|
month_names[month_names.length] = window.sL.longmonthsOctober
|
||||||
|
month_names[month_names.length] = window.sL.longmonthsNovember
|
||||||
|
month_names[month_names.length] = window.sL.longmonthsDecember
|
||||||
|
var system_date = new Date(Date.parse(tdate));
|
||||||
|
var hours = system_date.getHours();
|
||||||
|
var minutes = ('0'+system_date.getMinutes()).slice(-2);
|
||||||
|
var ampm = hours >= 12 ? 'pm' : 'am';
|
||||||
|
var time24hours = hours + ':' + minutes;
|
||||||
|
var time12hours = hours % 12;
|
||||||
|
time12hours = time12hours ? time12hours : 12; // the hour '0' should be '12'
|
||||||
|
if(ampm == 'am') { time12hours = window.sL.time12am.replace('{time}',time12hours + ':' + minutes);}
|
||||||
|
else { time12hours = window.sL.time12pm.replace('{time}',time12hours + ':' + minutes); }
|
||||||
|
return window.sL.longDateFormat.replace('{time24}',time24hours).replace('{hours}',hours).replace('{minutes}',minutes).replace('{time12}',time12hours).replace('{day}',system_date.getDate()).replace('{month}',month_names[system_date.getMonth()]).replace('{year}',system_date.getFullYear());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Return all URL:s in a string
|
||||||
|
·
|
||||||
|
· @param string: the string to search
|
||||||
|
·
|
||||||
|
· @return an array with the found urls
|
||||||
|
·
|
||||||
|
· · · · · · · · · · */
|
||||||
|
|
||||||
|
function findUrls(text) {
|
||||||
|
var source = (text || '').toString();
|
||||||
|
var urlArray = [];
|
||||||
|
var url;
|
||||||
|
var matchArray;
|
||||||
|
var regexToken = /(((ftp|https?):\/\/)[\-\w@:%_\+.~#?,&\/\/=]+)|((mailto:)?[_.\w-]+@([\w][\w\-]+\.)+[a-zA-Z]{2,3})/g;
|
||||||
|
while( (matchArray = regexToken.exec( source )) !== null ) {
|
||||||
|
var token = matchArray[0];
|
||||||
|
urlArray.push( token );
|
||||||
|
}
|
||||||
|
return urlArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Functions to show and remove the spinner
|
||||||
|
·
|
||||||
|
· · · · · · · · · · · · */
|
||||||
|
|
||||||
|
function display_spinner() {
|
||||||
|
if($('.spinner-wrap').length==0) {
|
||||||
|
$('body').prepend('<div class="spinner-wrap"><div class="spinner"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></div></div>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function remove_spinner() {
|
||||||
|
$('.spinner-wrap').remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Converts ...-attachment-links to spans
|
||||||
|
·
|
||||||
|
· (Attachments are loaded when queets expand)
|
||||||
|
·
|
||||||
|
· · · · · · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
function convertAttachmentMoreHref() {
|
||||||
|
$('a.attachment.more').each(function() {
|
||||||
|
if(typeof $(this).attr('href') != 'undefined') {
|
||||||
|
$(this).replaceWith($('<span class="attachment more" data-attachment-id="' + $(this).attr('href').substring(29) + '">…</span>'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Places the caret at the end of the contenteditable
|
||||||
|
·
|
||||||
|
· @param el: the contenteditable-element
|
||||||
|
·
|
||||||
|
· · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
function placeCaretAtEnd(el) {
|
||||||
|
el.focus();
|
||||||
|
if (typeof window.getSelection != "undefined"
|
||||||
|
&& typeof document.createRange != "undefined") {
|
||||||
|
var range = document.createRange();
|
||||||
|
range.selectNodeContents(el);
|
||||||
|
range.collapse(false);
|
||||||
|
var sel = window.getSelection();
|
||||||
|
sel.removeAllRanges();
|
||||||
|
sel.addRange(range);
|
||||||
|
} else if (typeof document.body.createTextRange != "undefined") {
|
||||||
|
var textRange = document.body.createTextRange();
|
||||||
|
textRange.moveToElementText(el);
|
||||||
|
textRange.collapse(false);
|
||||||
|
textRange.select();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Updates the local storage
|
||||||
|
·
|
||||||
|
· · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
function updateHistoryLocalStorage() {
|
||||||
|
var i=0;
|
||||||
|
var localStorageName = window.username + '-history-container';
|
||||||
|
var historyContainer = new Object();
|
||||||
|
$.each($('#history-container .stream-selection'), function(key,obj) {
|
||||||
|
historyContainer[i] = new Object();
|
||||||
|
historyContainer[i].dataStreamName = $(obj).attr('data-stream-name');
|
||||||
|
historyContainer[i].dataStreamHeader = $(obj).attr('data-stream-header');
|
||||||
|
i++;
|
||||||
|
});
|
||||||
|
localStorage[localStorageName] = JSON.stringify(historyContainer);
|
||||||
|
if($('#history-container .stream-selection').length==0) {
|
||||||
|
$('#history-container').css('display','none');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('#history-container').css('display','block');
|
||||||
|
}
|
||||||
|
$('#history-container').sortable({delay: 100});
|
||||||
|
$('#history-container').disableSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Loads history from local storage to menu
|
||||||
|
·
|
||||||
|
· · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
function loadHistoryFromLocalStorage() {
|
||||||
|
var localStorageName = window.username + '-history-container';
|
||||||
|
if(typeof localStorage[localStorageName] != "undefined") {
|
||||||
|
$('#history-container').css('display','block');
|
||||||
|
$('#history-container').html('');
|
||||||
|
var historyContainer = $.parseJSON(localStorage[localStorageName]);
|
||||||
|
$.each(historyContainer, function(key,obj) {
|
||||||
|
$('#history-container').append('<div class="stream-selection" data-stream-header="' + obj.dataStreamHeader + '" data-stream-name="' + obj.dataStreamName + '">' + obj.dataStreamHeader + '<i class="close-right"></i><i class="chev-right"></i></div>');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
updateHistoryLocalStorage();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Does stream need a ? or a &
|
||||||
|
·
|
||||||
|
· · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
function qOrAmp(stream) {
|
||||||
|
if(stream.substr(-5) == '.json') {
|
||||||
|
return '?';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return '&';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Count chars in queet box
|
||||||
|
·
|
||||||
|
· @param src: the queetbox
|
||||||
|
· @param trgt: the counter
|
||||||
|
· @param btn: the button
|
||||||
|
·
|
||||||
|
· · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
function countCharsInQueetBox(src,trgt,btn) {
|
||||||
|
var $src_txt = $('<div/>').append($.trim(src.html()).replace(/ /gi,'').replace(/<br>/i,'').replace(/<br>/gi,"x"));
|
||||||
|
var numchars = ($.trim($src_txt.text())).length;
|
||||||
|
trgt.html(140 - numchars);
|
||||||
|
|
||||||
|
// activate/deactivare button
|
||||||
|
if(src.html().replace(/\s/g, '').replace(/ /gi,'').replace(/<br>/gi,'') != unescape(src.attr('data-start-html')).replace(/\s/g, '').replace(/ /gi,'').replace(/<br>/gi,'')) {
|
||||||
|
if(src.text().replace(/\s/g, '').replace(/ /gi,'').replace(/<br>/gi,'').length==0) {
|
||||||
|
btn.removeClass('enabled');
|
||||||
|
btn.addClass('disabled');
|
||||||
|
}
|
||||||
|
else if((140-numchars) < 0) {
|
||||||
|
btn.removeClass('enabled');
|
||||||
|
btn.addClass('disabled');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
btn.removeClass('disabled');
|
||||||
|
btn.addClass('enabled');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
btn.removeClass('enabled');
|
||||||
|
btn.addClass('disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
// counter color
|
||||||
|
if((140-numchars) < 0) {
|
||||||
|
trgt.css('color','#D40D12');
|
||||||
|
}
|
||||||
|
else if(src.html().length == 0 || src.html() == '<br>' || src.html() == '<br />') {
|
||||||
|
trgt.removeAttr('style');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
trgt.removeAttr('style');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Remember my scroll position
|
||||||
|
·
|
||||||
|
· @param obj: jQuery object which position we want to remember
|
||||||
|
· @param id: id for position to remember
|
||||||
|
· @param offset: we might want to offset our remembered scroll, e.g. when stream-item gets margin after expand
|
||||||
|
·
|
||||||
|
· · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
function rememberMyScrollPos(obj,id,offset) {
|
||||||
|
if(typeof offset == 'undefined') {
|
||||||
|
var offset = 0;
|
||||||
|
}
|
||||||
|
if(typeof window.scrollpositions == 'undefined') { window.scrollpositions = new Object();}
|
||||||
|
window.scrollpositions[id] = obj.offset().top - $(window).scrollTop() - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· Go back to my scroll po
|
||||||
|
·
|
||||||
|
· @param obj: jQuery object to put in the remebered position
|
||||||
|
· @param id: id for remembered position
|
||||||
|
· @param animate: if we want to animate the scroll
|
||||||
|
· @param callback: function to run when animation stops
|
||||||
|
·
|
||||||
|
· · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
function backToMyScrollPos(obj,id,animate,callback) {
|
||||||
|
var pos = obj.offset().top-window.scrollpositions[id];
|
||||||
|
if(animate) {
|
||||||
|
if(typeof callback !== 'undefined'){
|
||||||
|
$('html, body').animate({ scrollTop: pos}, 1000, 'easeOutExpo',function(){
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('html, body').animate({ scrollTop: pos }, 1000, 'easeOutExpo');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('html, body').scrollTop(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ·
|
||||||
|
·
|
||||||
|
· outerHTML
|
||||||
|
·
|
||||||
|
· · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
jQuery.fn.outerHTML = function(s) {
|
||||||
|
return s
|
||||||
|
? this.before(s).remove()
|
||||||
|
: jQuery("<p>").append(this.eq(0).clone()).html();
|
||||||
|
};
|
1296
js/qvitter-1.js
Normal file
BIN
screenshot1.png
Normal file
After Width: | Height: | Size: 735 KiB |
BIN
screenshot2.png
Normal file
After Width: | Height: | Size: 596 KiB |
71
settings.php
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/* · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· Q V I T T E R ·
|
||||||
|
· ·
|
||||||
|
· http://github.com/hannesmannerheim/qvitter ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· <o) ·
|
||||||
|
· /_//// ·
|
||||||
|
· (____/ ·
|
||||||
|
· (o< ·
|
||||||
|
· o> \\\\_\ ·
|
||||||
|
· \\) \____) ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· ·
|
||||||
|
· Qvitter is free software: you can redistribute it and / or modify it ·
|
||||||
|
· under the terms of the GNU Affero General Public License as published by ·
|
||||||
|
· the Free Software Foundation, either version three of the License or (at ·
|
||||||
|
· your option) any later version. ·
|
||||||
|
· ·
|
||||||
|
· Qvitter is distributed in hope that it will be useful but WITHOUT ANY ·
|
||||||
|
· WARRANTY; without even the implied warranty of MERCHANTABILTY or FITNESS ·
|
||||||
|
· FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for ·
|
||||||
|
· more details. ·
|
||||||
|
· ·
|
||||||
|
· You should have received a copy of the GNU Affero General Public License ·
|
||||||
|
· along with Qvitter. If not, see <http://www.gnu.org/licenses/>. ·
|
||||||
|
· ·
|
||||||
|
· Contact h@nnesmannerhe.im if you have any questions. ·
|
||||||
|
· ·
|
||||||
|
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
|
||||||
|
// SITE TITLE
|
||||||
|
$sitetitle = 'Quitter';
|
||||||
|
|
||||||
|
// SITE DOMAIN
|
||||||
|
$siterootdomain = 'quitter.se'; // no http:// or https:// and no ending slash
|
||||||
|
|
||||||
|
// API ROOT
|
||||||
|
$apiroot = 'http://quitter.se/api/';
|
||||||
|
|
||||||
|
// TIME BETWEEN POLLING
|
||||||
|
$timebetweenpolling = 5000; // ms
|
||||||
|
|
||||||
|
// FORCE SSL ON AVATAR URLS AND SUCH
|
||||||
|
$forcessl = false;
|
||||||
|
|
||||||
|
// USE history.pushState TO REWRITE URLS IN THE LOCATION BAR (use with mod_rewrite)
|
||||||
|
// Try this rule in .htaccess:
|
||||||
|
// RewriteRule ^(search/)?(notice\?q=|group/|tag/)?([a-z0-9%]+)?(/all|/subscriptions|/subscribers|/groups|/replies|/favorites)?$ /theme/quitter-theme2/qvitter/index.php [L]
|
||||||
|
$usehistorypushstate = false;
|
||||||
|
|
||||||
|
// FULL PATH TO THIS QVITTER APP
|
||||||
|
// (can be left blank, but if you're not doing mod_rewrites you need this)
|
||||||
|
$qvitterpath = ''; // WITH trailing slash!!
|
||||||
|
|
||||||
|
|
||||||
|
/* · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
|
||||||
|
· ·
|
||||||
|
· (o> >o) ·
|
||||||
|
· \\\\_\ /_//// .
|
||||||
|
· \____) (____/ ·
|
||||||
|
· ·
|
||||||
|
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */
|
||||||
|
|
||||||
|
?>
|