Showing preview only (3,024K chars total). Download the full file or copy to clipboard to get everything.
Repository: IBBoard/cawbird
Branch: master
Commit: 55a19e86b0e0
Files: 265
Total size: 2.8 MB
Directory structure:
gitextract_nws3r4s9/
├── ._vimrc
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ └── feature_request.md
│ └── workflows/
│ └── main.yml
├── .gitignore
├── .tx/
│ └── config
├── COPYING
├── README.md
├── cawbird.gresource.xml
├── data/
│ ├── cawbird.1
│ ├── meson.build
│ ├── meson_post_install.py
│ ├── render-icons.sh
│ ├── uk.co.ibboard.cawbird.appdata.xml.in
│ ├── uk.co.ibboard.cawbird.desktop.in
│ ├── uk.co.ibboard.cawbird.gschema.xml
│ └── uk.co.ibboard.cawbird.service.in
├── examples/
│ ├── accountdialog.vala
│ ├── meson.build
│ └── tweetstates.vala
├── flatpak/
│ └── uk.co.ibboard.cawbird.json
├── meson.build
├── meson_options.txt
├── notes.md
├── po/
│ ├── LINGUAS
│ ├── POTFILES.in
│ ├── POTFILES.skip
│ ├── ar.po
│ ├── ast.po
│ ├── ca.po
│ ├── ca@valencia.po
│ ├── cawbird.pot
│ ├── da.po
│ ├── de.po
│ ├── de_DE.po
│ ├── en_GB.po
│ ├── en_US.po
│ ├── eo.po
│ ├── es.po
│ ├── es_419.po
│ ├── es_MX.po
│ ├── es_VE.po
│ ├── fa.po
│ ├── fi.po
│ ├── fr.po
│ ├── ga.po
│ ├── gd.po
│ ├── gl.po
│ ├── hi.po
│ ├── hu.po
│ ├── id.po
│ ├── it.po
│ ├── ja.po
│ ├── ko.po
│ ├── lt.po
│ ├── meson.build
│ ├── nb.po
│ ├── nl.po
│ ├── pl.po
│ ├── pt.po
│ ├── pt_BR.po
│ ├── ro.po
│ ├── ru.po
│ ├── sr.po
│ ├── sr_BA@latin.po
│ ├── tr.po
│ ├── uk_UA.po
│ ├── zh_CN.po
│ └── zh_TW.po
├── sql/
│ ├── accounts/
│ │ ├── Create.1.sql
│ │ ├── Create.2.sql
│ │ ├── Create.3.sql
│ │ ├── Create.4.sql
│ │ ├── Create.5.sql
│ │ ├── Create.6.sql
│ │ └── Create.7.sql
│ └── init/
│ ├── Create.1.sql
│ ├── Create.2.sql
│ ├── Create.3.sql
│ └── Create.4.sql
├── src/
│ ├── Account.vala
│ ├── Cawbird.vala
│ ├── CbAvatarCache.c
│ ├── CbAvatarCache.h
│ ├── CbBundle.c
│ ├── CbBundle.h
│ ├── CbBundleHistory.c
│ ├── CbBundleHistory.h
│ ├── CbDeltaUpdater.c
│ ├── CbDeltaUpdater.h
│ ├── CbEmojiChooser.c
│ ├── CbEmojiChooser.h
│ ├── CbFilter.c
│ ├── CbFilter.h
│ ├── CbGtkCompat.h
│ ├── CbMedia.c
│ ├── CbMedia.h
│ ├── CbMediaDownloader.c
│ ├── CbMediaDownloader.h
│ ├── CbMediaImageWidget.c
│ ├── CbMediaImageWidget.h
│ ├── CbMediaVideoWidget.c
│ ├── CbMediaVideoWidget.h
│ ├── CbMessageReceiver.c
│ ├── CbMessageReceiver.h
│ ├── CbSnippetManager.c
│ ├── CbSnippetManager.h
│ ├── CbSurfaceProgress.c
│ ├── CbSurfaceProgress.h
│ ├── CbTextTransform.c
│ ├── CbTextTransform.h
│ ├── CbTweet.c
│ ├── CbTweet.h
│ ├── CbTweetModel.c
│ ├── CbTweetModel.h
│ ├── CbTwitterItem.c
│ ├── CbTwitterItem.h
│ ├── CbTypes.c
│ ├── CbTypes.h
│ ├── CbUserCompletionModel.c
│ ├── CbUserCompletionModel.h
│ ├── CbUserCounter.c
│ ├── CbUserCounter.h
│ ├── CbUserStream.c
│ ├── CbUserStream.h
│ ├── CbUtils.c
│ ├── CbUtils.h
│ ├── ComposedTweet.vala
│ ├── DMManager.vala
│ ├── DMPage.vala
│ ├── DMThreadsPage.vala
│ ├── DefaultTimeline.vala
│ ├── FavoritesTimeline.vala
│ ├── FilterPage.vala
│ ├── HomeTimeline.vala
│ ├── IPage.vala
│ ├── ListStatusesPage.vala
│ ├── ListsPage.vala
│ ├── MainWidget.vala
│ ├── MainWindow.vala
│ ├── MediaUpload.vala
│ ├── MentionsTimeline.vala
│ ├── NotificationManager.vala
│ ├── OAuthProxyCallWithBody.vala
│ ├── OAuthProxyCallWithQueryString.vala
│ ├── ProfilePage.vala
│ ├── SearchPage.vala
│ ├── Settings.vala
│ ├── TweetInfoPage.vala
│ ├── Twitter.vala
│ ├── UserEventReceiver.vala
│ ├── async/
│ │ ├── Collect.vala
│ │ └── CollectById.vala
│ ├── cawbird.vapi
│ ├── libtl/
│ │ ├── data.h
│ │ ├── libtweetlength.c
│ │ └── libtweetlength.h
│ ├── list/
│ │ ├── AddListEntry.vala
│ │ ├── DMListEntry.vala
│ │ ├── DMThreadEntry.vala
│ │ ├── FavImageRow.vala
│ │ ├── FilterListEntry.vala
│ │ ├── ListListEntry.vala
│ │ ├── NewListEntry.vala
│ │ ├── SnippetListEntry.vala
│ │ ├── StartConversationEntry.vala
│ │ ├── TweetListEntry.vala
│ │ ├── UserFilterEntry.vala
│ │ └── UserListEntry.vala
│ ├── main.vala
│ ├── model/
│ │ └── DMThreadsModel.vala
│ ├── sql/
│ │ ├── BaseStatement.vala
│ │ ├── Database.vala
│ │ ├── DeleteStatement.vala
│ │ ├── InsertStatement.vala
│ │ ├── SelectStatement.vala
│ │ └── UpdateStatement.vala
│ ├── util/
│ │ ├── Benchmark.vala
│ │ ├── Dirs.vala
│ │ ├── ListUtils.vala
│ │ ├── TweetUtils.vala
│ │ ├── UserCompletion.vala
│ │ ├── UserUtils.vala
│ │ └── Utils.vala
│ ├── widgets/
│ │ ├── AccountCreateWidget.vala
│ │ ├── AddImageButton.vala
│ │ ├── AspectImage.vala
│ │ ├── AvatarBannerWidget.vala
│ │ ├── AvatarWidget.vala
│ │ ├── BadgeRadioButton.vala
│ │ ├── CompletionTextView.vala
│ │ ├── ComposeImageManager.vala
│ │ ├── CropWidget.vala
│ │ ├── DMPlaceholderBox.vala
│ │ ├── DoubleTapButton.vala
│ │ ├── FavImageView.vala
│ │ ├── FollowButton.vala
│ │ ├── ImpostorWidget.vala
│ │ ├── LazyMenuButton.vala
│ │ ├── ListBox.vala
│ │ ├── MediaButton.vala
│ │ ├── MediaButtonSurface.vala
│ │ ├── MultiMediaWidget.vala
│ │ ├── PixbufButton.vala
│ │ ├── ReplyEntry.vala
│ │ ├── ResizableImage.vala
│ │ ├── ScrollWidget.vala
│ │ ├── TextButton.vala
│ │ ├── TweetListBox.vala
│ │ └── UserListsWidget.vala
│ └── window/
│ ├── AboutDialog.vala
│ ├── AccountDialog.vala
│ ├── ComposeTweetWindow.vala
│ ├── ImageDescriptionWindow.vala
│ ├── MediaDialog.vala
│ ├── ModifyFilterDialog.vala
│ ├── ModifySnippetDialog.vala
│ ├── SettingsDialog.vala
│ └── UserListDialog.vala
├── tests/
│ ├── avatarcache.vala
│ ├── avatardownload.vala
│ ├── bundlehistory.vala
│ ├── dmmanager.vala
│ ├── filters.vala
│ ├── friends.vala
│ ├── inlinemediadownloader.vala
│ ├── meson.build
│ ├── texttransform.vala
│ ├── tweetmodel.vala
│ ├── tweetparsing.vala
│ ├── twitteritem.vala
│ ├── usercompletionmodel.vala
│ ├── usercounter.vala
│ └── utils.vala
├── ui/
│ ├── about-dialog.ui
│ ├── account-create-widget.ui
│ ├── account-dialog.ui
│ ├── cb-emoji-chooser.ui
│ ├── compose-window.ui
│ ├── dm-page.ui
│ ├── dm-thread-entry.ui
│ ├── filter-list-entry.ui
│ ├── filter-page.ui
│ ├── image-description-window.ui
│ ├── list-list-entry.ui
│ ├── list-statuses-page.ui
│ ├── media-dialog.ui
│ ├── menus.ui
│ ├── modify-filter-dialog.ui
│ ├── modify-snippet-dialog.ui
│ ├── new-list-entry.ui
│ ├── profile-page.ui
│ ├── search-page.ui
│ ├── settings-dialog.ui
│ ├── shortcuts-window.ui
│ ├── start-conversation-entry.ui
│ ├── style.css
│ ├── tweet-info-page.ui
│ ├── tweet-list-entry.ui
│ ├── user-filter-entry.ui
│ ├── user-list-entry.ui
│ └── user-lists-widget.ui
└── vapi/
├── cawbird-internal.vapi
├── config.vapi
└── libtl.vapi
================================================
FILE CONTENTS
================================================
================================================
FILE: ._vimrc
================================================
set wildignore+=*.c,*\~,CMakeFiles,Makefile,*.lo,test-driver,*.trs,*.stamp,Makefile.in,*.la,*.svg
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us fix problems and errors
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**System details:**
- OS: [e.g. Ubuntu 18.04]
- Version: [e.g. 1.0.4-61.2]
- Package type: [e.g. Official RPM/Deb, Snap, Flatpak, distro package, or custom build]
**Additional context**
Add any other context about the problem here.
Running `G_MESSAGES_DEBUG=cawbird cawbird` can give useful debug output.
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for a change or new feature
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
================================================
FILE: .github/workflows/main.yml
================================================
name: GitHub Polls Actions Bot
on:
issue_comment:
types: [created, edited] # issue comment is created or edited
issues:
types: [opened, edited] # issue is opened or edited
jobs:
polls:
runs-on: ubuntu-latest
steps:
- uses: imjohnbo/gh-polls-bot-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
================================================
FILE: .gitignore
================================================
# Build Directories
build/
_build/
flatpak/_build
flatpak/.flatpak-builder
valgrind*
data/consumer_k.dat
data/consumer_s.dat
================================================
FILE: .tx/config
================================================
[main]
host = https://transifex.com
[corebird.corebirdpot]
file_filter = po/<lang>.po
host = https://transifex.com
source_file = po/corebird.pot
source_lang = en
type = PO
lang_map = id_ID: id, ro_RO: ro, pt_PT: pt, ko_KR: ko, hi_IN: hi, ja_JP: ja, tr_TR: tr
================================================
FILE: COPYING
================================================
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 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 General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is 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. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
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.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
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 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. Use with the GNU Affero General Public License.
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 Affero 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 special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU 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 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 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 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 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 General Public License for more details.
You should have received a copy of the GNU 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 the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
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 GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
================================================
FILE: README.md
================================================
# Cawbird 1.5
## DEPRECATION NOTICE
⚠ As of January 2023, Cawbird for Twitter is no longer being developed ⚠
This is because Twitter changed the Developer Agreement to prohibit "creating a substitute for Twitter Applications" and revoked our primary API keys around 20th January.
The next generation of Cawbird will be a Mastodon client. Follow Cawbird Toot Point Oh (codename NewCaw) at https://github.com/CodedOre/NewCaw
## Introduction
<a href="https://ibboard.co.uk/cawbird/#screenshots"><img src="./screenshot1.jpg" style="float:right; margin-left: 1em;" /></a>
[Cawbird](https://ibboard.co.uk/cawbird/) ~~is~~ was a fork of the [Corebird](https://corebird.baedert.org/) Twitter client from Baedert, which became unsupported after Twitter disabled the streaming API.
Cawbird ~~works~~ worked with the new APIs and includes a few fixes and modifications that have historically been patched in to IBBoard's custom Corebird build on his personal Open Build Service account<sup>[1](#footnote1)</sup>.
## Packaging and installation
Cawbird packages are built in the [Cawbird Open Build Service project](https://build.opensuse.org/project/show/home:IBBoard:cawbird). They can be installed from the [Cawbird download page](https://software.opensuse.org//download.html?project=home%3AIBBoard%3Acawbird&package=cawbird).
<a href="https://software.opensuse.org//download.html?project=home%3AIBBoard%3Acawbird&package=cawbird" style="display: inline-block; padding: 0.5em 1em; border: 1px solid #000; border-radius: 0.5em; background: #444; color: #eee; font-weight: bold">**Install Cawbird**</a>
These packages are currently available for:
* openSUSE
* openSUSE Tumbleweed
* openSUSE Leap 15.2
* openSUSE Leap 15.3
* Fedora
* Fedora 32
* Fedora 33
* Fedora 34
* Fedora Rawhide
* CentOS
* CentOS 7
* CentOS 8 (including Streams)
* Ubuntu
* Ubuntu 18.04 (Bionic Beaver)
* Ubuntu 20.04 (Focal Fossa)
* Ubuntu 20.10 (Groovy Gorilla)
* Ubuntu 21.04 (Hirstue Hippo)
* Debian
* 10 (Buster)
* Testing
* Unstable
* Raspbian 10
i586, x86_64 (amd64), aarch64 (arm64) and armv7l are available on most platforms (where supported by the distro).
### Official distro repositories
The following distros currently have their own official packages:
* [Alpine Linux / postmarketOS (Edge)](https://pkgs.alpinelinux.org/packages?name=cawbird&branch=edge)
* `sudo apk add cawbird`
* [Arch Linux](https://www.archlinux.org/packages/community/x86_64/cawbird/) ("Community")
* `pacman -Syu cawbird`
* [Fedora (30+)](https://apps.fedoraproject.org/packages/cawbird)
* `sudo dnf install cawbird`
* [Gentoo](https://packages.gentoo.org/packages/net-im/cawbird)
* `emerge net-im/cawbird`
* [Guix](https://guix.gnu.org/en/packages/cawbird-1.4.1/)
* `guix install cawbird`
* [NixOS (19.09+)](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/networking/cawbird/default.nix)
* `nix-shell -p cawbird` for testing, `nix-env -iA cawbird` for permanent installation
* [Solus](https://dev.getsol.us/source/cawbird/)
* `sudo eopkg it cawbird`
## Community builds
* [Cawbird Snap](https://snapcraft.io/cawbird) on Snapcraft.io
* [Cawbird Flatpak](https://flathub.org/apps/details/uk.co.ibboard.cawbird) on Flathub.org
* Arch Linux (AUR):
* [Cawbird-git](https://aur.archlinux.org/packages/cawbird-git)
### Dependencies
Twitter uses specific codecs for videos. These are provided by `libav` and are not included in the core repositories of many distros. The following additional repositories are known to include the required libraries:
* openSUSE - [Packman](http://packman.links2linux.org/)
* Fedora/CentOS - [RPMFusion](https://rpmfusion.org/)
* Ubuntu - Universe
## Shortcuts
| Key | Description |
| :-----: | :----------- |
| `Ctrl + t` | Compose Tweet |
| `Back` | Go one page back (this can be triggered via the back button on the keyboard, the back thumb button on the mouse or `Alt + Left`) |
| `Forward` | Go one page forward (this can be triggered via the forward button on the keyboard, the forward thumb button on the mouse or `Alt + Right`) |
| `Alt + num` | Go to page `num` (between 1 and 7 at the moment) |
| `Ctrl + Shift + s` | Show/Hide topbar |
| `Ctrl + p` | Show account settings |
| `Ctrl + k` | Show account list |
| `Ctrl + Shift + p` | Show application settings |
When a tweet is focused (via keynav):
* `r` - reply
* `tt` - retweet
* `f` - favorite
* `q` - quote
* `dd` - delete
* `Return` - Show tweet details
* `k` - Print tweet details to stdout (debug builds)
## Limitations
Due to [changes in the Twitter API](https://developer.twitter.com/en/docs/accounts-and-users/subscribe-account-activity/migration/introduction), Cawbird has the following limitations:
* Cawbird will update every two minutes
* Cawbird does not get notified of the following actions when performed outside Cawbird, which will be refreshed on restart:
* Unfavourite
* Follow/Unfollow
* Block/Unblock
* Mute/Unmute
* DM deletion
* Some list changes
All limitations are limitations imposed by Twitter and are not the fault of the Cawbird client. They have affected [all third-party client applications](http://apps-of-a-feather.com/).
Cawbird has also been unable to implement the following features because Twitter did not provide a way for third-party applications to get the data:
* Notification of Likes, RTs, quote tweets and any other interaction that appears in the "All" tab of twitter.com's Notifications but not in "Mentions"
* No API is available for other notifications, only a [mentions API](https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-mentions_timeline)
* Lists of who liked a specific tweet
* No API is available, only a list of which tweets a user has liked
* DMs to Groups
* Twitter's API only supports one-to-one DMs
* Twitter explicitly [closed a request for this API](https://twitterdevfeedback.uservoice.com/forums/921790-twitter-developer-labs/suggestions/37689256-allow-access-to-dm-group-conversations-via-twitter) as "not a priority"
* Polls
* The free API does not include polls as tweet "entities"
* Twitter doesn't even mark posts so that we can direct people to the web
* Twitter's "[Bookmarks](https://blog.twitter.com/en_us/topics/product/2018/an-easier-way-to-save-and-share-tweets.html)" system
* No API is available
* Full threads in a single request
* No API is available
* Replies older than seven days
* The free search is limited to returning results from the last seven days
* All replies to a tweet
* No API is available and the search results are not guaranteed to find all replies
* Twitter [Cards](https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/abouts-cards)
* No API is available
* Twitter doesn't even mark posts so that we can direct people to the web
* This results in @TwitterDev [posting a message](https://mobile.twitter.com/TwitterDev/status/1222596295090757636) that many devs can't see!
As of July 2020, Twitter has [announced v2 of the API](https://blog.twitter.com/developer/en_us/topics/tools/2020/introducing_new_twitter_api.html) and may support some of these features. We are [looking in to this](https://github.com/IBBoard/cawbird/issues/180) as that parts of the API are made available.
## Known issues
There are no current known issues with running Cawbird.
Previously, the following issues have occurred that were outside of our control:
* Due to a [bug in GnuTLS](https://gitlab.com/gnutls/gnutls/issues/841#note_225110002), Cawbird has suffered from occasional TLS errors. This has been handled under [Cawbird bug 9](https://github.com/IBBoard/cawbird/issues/9) and GnuTLS have released a fix for the underlying problem
* Due to a [bug in GStreamer 1.16.1](https://github.com/IBBoard/cawbird/pull/42#issuecomment-539437887), Cawbird suffered from glitchy audio and video when playing media. This has now been fixed in GStreamer
* Some combination of GStreamer, GTK and the Video Acceleration API (VAAPI) on some Intel chips can [cause corruption of videos](https://github.com/IBBoard/cawbird/issues/279). This is an [old and on-going problem](https://github.com/baedert/corebird/issues/540). Removing `gstreamer-vaapi` or equivalent resolves the problem.
* "Fragment downloading has failed consecutive times" messages from GStreamer appear to be due to changes in GStreamer's `adaptivedemux` code that are [fixed in v1.18.1](https://gstreamer.freedesktop.org/releases/1.18/#1.18.2)
## Translations
Since February 2020, there has been a [Cawbird project on Transifex](https://www.transifex.com/cawbird/cawbird/dashboard/). Users can sign up on Transifex for free to help translate Cawbird.
## Testing
Since August 2020, there has been a [Cawbird "unstable" package](https://software.opensuse.org//download.html?project=home%3AIBBoard%3Acawbird-unstable&package=cawbird-unstable) built on the Open Build Service. These packages are intended for users who can't build Cawbird from source but want to test new features.
**Do not** use the unstable release unless you are testing new features and understand the risks. *They are not intended for everyday use*. They will be updated intermittently with new features from `git master`. They may have bugs. They may not get patched. They may be behind the main release. They may break things and eat your homework.
It is recommended that you backup `~/.config/cawbird` before running Cawbird-Unstable.
## Contributing
All contributions are welcome (artwork, design, code, just ideas, etc.) but if you're planning to
actively change something bigger, talk to me first.
## Compiling Cawbird
### Preparation
Twitter clients need keys and secrets so that Twitter can go through the OAuth process. Cawbird used to ship
with a standard set of but has always supported custom keys through schema settings. However, that wasn't convenient for software builds. Cawbird now supports:
a) per-user tokens and secrets (so each user uses a different "app")
b) configuration of the default token and secret at build time
What this means for developers is that you need to supply two build options with the key and the secret before the software will build. To stop them being trivially identifiable, we base64 encode them.
If you wish to build your own "micro-fork" of the application then register at [developer.twitter.com](https://developer.twitter.com/) and create an application. To base64 encode the keys you can run `echo -n "<value>" | base64`.
Reasons you may wish to micro-fork Cawbird:
* You want to package a modified version with your own patches (as IBBoard used to do with Corebird)
* You want to appear retro and use the old Corebird keys to confuse people
* You want to check whether you're getting hit by Twitter limiting *applications*
(not just users - all users of the app in aggregate) to 100,000 calls to some endpoints ([docs](https://developer.twitter.com/en/docs/twitter-api/v1/tweets/timelines/api-reference/get-statuses-mentions_timeline))
Alternatively you can continue using the default keys by using the values `VmY5dG9yRFcyWk93MzJEZmhVdEk5Y3NMOA==` and `MThCRXIxbWRESDQ2Y0podzVtVU13SGUyVGlCRXhPb3BFRHhGYlB6ZkpybG5GdXZaSjI=` respectively.
### Compiling
Cawbird uses the Meson build system rather than the more archaic autoconf/make combination. Building is as simple as:
```Bash
meson build -Dconsumer_key_base64=<your-base64-key> -Dconsumer_secret_base64=<your-base64-secret>
ninja -C build
```
If you want to test translations locally then you will also need to:
* pass `-Dlocaltextdomain=true` to meson
* run `ninja -C build cawbird-gmo` to generate the binary `.mo` translations
* run `for file in po/*.gmo; do mkdir -p "${file/.gmo}/LC_MESSAGES/"; cp $file "${file/.gmo}/LC_MESSAGES/cawbird.mo"; done` to put the `.mo` files in the expected places
* run `pushd build; ./cawbird; popd` to run Cawbird from the build directory
* to test a different language, run `cd build; LANGUAGE=aa_BB ./cawbird` with the appropriate language code
Note that executing `build/cawbird` may result in one of the following errors:
```Bash
Settings schema 'uk.co.ibboard.cawbird' is not installed
Settings schema 'uk.co.ibboard.cawbird' does not contain a key named 'foo'
```
To fix this, use the schemas from the build directory:
```Bash
GSETTINGS_SCHEMA_DIR=build/data/ GSETTINGS_BACKEND='memory' build/cawbird
```
Cawbird installs its application icon into `/usr/share/icons/hicolor/`, so an appropriate call to `gtk-update-icon-cache` might be needed.
### Build Dependencies
* `gtk+-3.0 >= 3.22`
* `glib-2.0 >= 2.44`
* `json-glib-1.0`
* `sqlite3`
* `libsoup-2.4`
* `librest-0.7`
* `liboauth`
* `gettext >= 0.19.7`
* `vala >= 0.28` (makedep)
* `meson` (makedep)
* `gst-plugins-base-1.0` (for playbin, disable by passing `-Dvideo=false` to Meson)
* `gst-plugins-bad-1.0 >= 1.6` or `gst-plugins-good-1.0` (disable by passing `-Dvideo=false` to Meson, default enabled)
* Requires the `element-gtksink` feature, provided by `gstreamer1.0-gtk` on Ubuntu-based systems,
`gstreamer1-plugins-bad-free-gtk` on older RPM-based systems and `gstreamer1-plugins-good-gtk` on
newer RPM-based systems
* `gst-libav-1.0` (disable by passing `-Dvideo=false` to Meson, default enabled)
* `gspell-1 >= 1.2` (for spellchecking, disable by passing `-Dspellcheck=false` to Meson, default enabled)
Note that the above packages are just rough estimations, the actual package names on your distribution may vary and may require additional repositories (e.g. RPMFusion in Fedora, or Packman in openSUSE)
If you pass `-Dvideo=false` to the Meson script, you don't need any gstreamer dependency but won't be able to view any videos.
## Copyright
Cawbird is released under the GPL v3 (or later) - see [COPYING](./COPYING) for more details.
The [video fallback image](data/symbolic/apps/cawbird-video-placeholder.svg) is a Creative Commons "CC-BY-3.0" licensed work [by Iris Li](https://thenounproject.com/term/film-reel/20395/).
## Social Media
* [@CawbirdClient on Twitter](https://twitter.com/cawbirdclient)
* <a rel="me" href="https://mastodon.social/@cawbird">@Cawbird on Mastodon.social</a>
## Footnotes
<a name="footnote1"></a>1: [home:IBBoard:desktop](https://build.opensuse.org/project/show/home:IBBoard:desktop)
================================================
FILE: cawbird.gresource.xml
================================================
<gresources>
<gresource prefix="/uk/co/ibboard/cawbird">
<file preprocess="xml-stripblanks" alias="gtk/menus.ui">ui/menus.ui</file>
<file preprocess="xml-stripblanks">ui/settings-dialog.ui</file>
<file preprocess="xml-stripblanks">ui/account-create-widget.ui</file>
<file preprocess="xml-stripblanks">ui/compose-window.ui</file>
<file preprocess="xml-stripblanks">ui/image-description-window.ui</file>
<file preprocess="xml-stripblanks">ui/tweet-list-entry.ui</file>
<file preprocess="xml-stripblanks">ui/tweet-info-page.ui</file>
<file preprocess="xml-stripblanks">ui/about-dialog.ui</file>
<file preprocess="xml-stripblanks">ui/dm-thread-entry.ui</file>
<file preprocess="xml-stripblanks">ui/profile-page.ui</file>
<file preprocess="xml-stripblanks">ui/dm-page.ui</file>
<file preprocess="xml-stripblanks">ui/search-page.ui</file>
<file preprocess="xml-stripblanks">ui/user-list-entry.ui</file>
<file preprocess="xml-stripblanks">ui/start-conversation-entry.ui</file>
<file preprocess="xml-stripblanks">ui/list-statuses-page.ui</file>
<file preprocess="xml-stripblanks">ui/list-list-entry.ui</file>
<file preprocess="xml-stripblanks">ui/new-list-entry.ui</file>
<file preprocess="xml-stripblanks">ui/user-lists-widget.ui</file>
<file preprocess="xml-stripblanks">ui/filter-page.ui</file>
<file preprocess="xml-stripblanks">ui/filter-list-entry.ui</file>
<file preprocess="xml-stripblanks">ui/modify-filter-dialog.ui</file>
<file preprocess="xml-stripblanks">ui/user-filter-entry.ui</file>
<file preprocess="xml-stripblanks">ui/account-dialog.ui</file>
<file preprocess="xml-stripblanks">ui/media-dialog.ui</file>
<file preprocess="xml-stripblanks">ui/modify-snippet-dialog.ui</file>
<file preprocess="xml-stripblanks">ui/shortcuts-window.ui</file>
<file preprocess="xml-stripblanks">ui/cb-emoji-chooser.ui</file>
<file>data/symbolic/apps/cawbird-compose-symbolic.svg</file>
<file>data/symbolic/apps/cawbird-conversation-symbolic.svg</file>
<file>data/symbolic/apps/cawbird-dms-symbolic.svg</file>
<file>data/symbolic/apps/cawbird-filter-symbolic.svg</file>
<file>data/symbolic/apps/cawbird-mentions-symbolic.svg</file>
<file>data/symbolic/apps/cawbird-new-window-symbolic.svg</file>
<file>data/symbolic/apps/cawbird-reply-symbolic.svg</file>
<file>data/symbolic/apps/cawbird-retweet-symbolic.svg</file>
<file>data/symbolic/apps/cawbird-translate-symbolic.svg</file>
<file>data/symbolic/apps/cawbird-profile-symbolic.svg</file>
<file>data/symbolic/apps/cawbird-favorite-symbolic.svg</file>
<file>data/symbolic/apps/cawbird-user-home-symbolic.svg</file>
<file>data/symbolic/apps/cawbird-edit-find-symbolic.svg</file>
<file>data/symbolic/apps/cawbird-video-placeholder.svg</file>
<file>data/play.png</file>
<file>data/play@2.png</file>
<file>data/verified-small.png</file>
<file>data/verified-small@2.png</file>
<file>data/verified-large.png</file>
<file>data/verified-large@2.png</file>
<file>data/protected-account-small.png</file>
<file>data/protected-account-small@2.png</file>
<file>data/protected-account-large.png</file>
<file>data/protected-account-large@2.png</file>
<file>data/no_avatar.png</file>
<file>data/null_avatar.png</file>
<file>data/no_banner.png</file>
<file>data/withheld_avatar.png</file>
<file>ui/style.css</file>
<file>sql/init/Create.1.sql</file>
<file>sql/init/Create.2.sql</file>
<file>sql/init/Create.3.sql</file>
<file>sql/init/Create.4.sql</file>
<file>sql/accounts/Create.1.sql</file>
<file>sql/accounts/Create.2.sql</file>
<file>sql/accounts/Create.3.sql</file>
<file>sql/accounts/Create.4.sql</file>
<file>sql/accounts/Create.5.sql</file>
<file>sql/accounts/Create.6.sql</file>
<file>sql/accounts/Create.7.sql</file>
</gresource>
</gresources>
================================================
FILE: data/cawbird.1
================================================
.TH "cawbird" "1" "08. Feb. 2014" "man page by Malcolm J Lewis" ""
.SH NAME
.B
cawbird
- Native Gtk+ Twitter client for the Linux desktop.
.SH SYNOPSIS
.B
cawbird [--tweet=@screen_name]
.SH DESCRIPTION
- Cawbird is a native GTK+ twitter client that provides vital features such as Direct Messages (DMs), tweet notifications, conversation views.
- Additional features include the ability to change to the GTK+ dark theme, searching and media uploads.
.SH KEYBOARD SHORTCUTS [command]
.B
[Ctrl + t] -
Compose tweet
.B
[Back] -
Go one page back (this can be triggered via the back button on the keyboard, the back thumb button on the mouse or [Alt + Left])
.B
[Forward] -
Go one page forward(this can be triggered via the forward button on the keyboard, the forward thumb button on the mouse or [Alt + Right])
.B
[Alt + num] -
Go to page [num] (between 1 and 5 at the moment)
.B
[Ctrl + Shift + s] -
Show/Hide sidebar
.B
When a tweet is focused (via keynav)
.B
[r] -
Reply
.B
[tt] -
Retweet
.B
[l] -
Like
.B
[dd] -
Delete
.B
[Return] -
Show tweet details
.SH AUTHOR
Updated by IBBoard.
Originally written as Corebird by Timm Bäder.
.SH HOMEPAGE
https://ibboard.co.uk/cawbird/
.SH REPORTING BUGS
https://github.com/ibboard/cawbird/issues
================================================
FILE: data/meson.build
================================================
i18n = import('i18n')
install_data(
'uk.co.ibboard.cawbird.gschema.xml',
install_dir: join_paths(get_option('datadir'), 'glib-2.0', 'schemas')
)
meson.add_install_script('meson_post_install.py')
i18n.merge_file(
input: 'uk.co.ibboard.cawbird.desktop.in',
output: 'uk.co.ibboard.cawbird.desktop',
po_dir: '../po/',
type: 'desktop',
install: true,
install_dir: join_paths(get_option('datadir'), 'applications')
)
if get_option('appdata')
i18n.merge_file(
input: 'uk.co.ibboard.cawbird.appdata.xml.in',
output: 'uk.co.ibboard.cawbird.appdata.xml',
po_dir: '../po/',
type: 'xml',
install: true,
install_dir: join_paths(get_option('datadir'), 'metainfo')
)
endif
install_man('cawbird.1')
conf = configuration_data()
conf.set('bindir', join_paths(get_option('prefix'), 'bin'))
configure_file(
input: 'uk.co.ibboard.cawbird.service.in',
output: 'uk.co.ibboard.cawbird.service',
configuration: conf,
install_dir: join_paths(get_option('datadir'), 'dbus-1/services')
)
gnome.compile_schemas(
build_by_default: true,
depend_files: ['uk.co.ibboard.cawbird.gschema.xml']
)
# Install all application icons in one go
install_subdir(
'hicolor',
install_dir: join_paths(get_option('datadir'), 'icons')
)
================================================
FILE: data/meson_post_install.py
================================================
#!/usr/bin/env python3
import os
import subprocess
schemadir = os.path.join(os.environ['MESON_INSTALL_PREFIX'], 'share', 'glib-2.0', 'schemas')
if not os.environ.get('DESTDIR'):
print('Compiling gsettings schemas...')
subprocess.call(['glib-compile-schemas', schemadir])
================================================
FILE: data/render-icons.sh
================================================
#!/bin/bash
sizes=(16 24 32 48 64 96)
for size in ${sizes[@]}
do
rsvg-convert ./uk.co.ibboard.cawbird.svg --width="${size}" --height="${size}" \
--format=png -o "./hicolor/${size}x${size}/apps/uk.co.ibboard.cawbird.png"
done
cp ./uk.co.ibboard.cawbird.svg ./hicolor/scalable/apps/uk.co.ibboard.cawbird.svg
================================================
FILE: data/uk.co.ibboard.cawbird.appdata.xml.in
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2013 Ryan Lerch <ryanlerch@fedoraproject.org> -->
<component type="desktop">
<id>uk.co.ibboard.cawbird.desktop</id>
<name>Cawbird</name>
<summary>Twitter Client</summary>
<metadata_license>CC0-1.0</metadata_license>
<translation type="gettext">cawbird</translation>
<description>
<p>
Cawbird is a native GTK+ twitter client that provides vital features such as Direct Messages (DMs), tweet notifications, conversation views.
</p>
<p>
Additional features include local viewing of videos, multiple inline images, Lists, Filters, multiple accounts, etc.
</p>
</description>
<url type="homepage">https://ibboard.co.uk/cawbird/</url>
<launchable type="desktop-id">uk.co.ibboard.cawbird.desktop</launchable>
<screenshots>
<screenshot height="1032" width="481" type="default">
<image>https://ibboard.co.uk/cawbird/appdata/screenshot1.jpg</image>
<caption>Generic timeline view when using Cawbird</caption>
</screenshot>
<screenshot height="956" width="564">
<image>https://ibboard.co.uk/cawbird/appdata/screenshot2.jpg</image>
<caption>Typical Twitter profile</caption>
</screenshot>
<screenshot height="956" width="564">
<image>https://ibboard.co.uk/cawbird/appdata/screenshot3.jpg</image>
<caption>Account settings can be configured</caption>
</screenshot>
<screenshot height="688" width="1283">
<image>https://ibboard.co.uk/cawbird/appdata/screenshot4.jpg</image>
<caption>Cawbird in different themes (Adwaita, Adwaita dark variant, High Contrast and Adwaita Dark Green)</caption>
</screenshot>
</screenshots>
<kudos>
<kudo>AppMenu</kudo>
<kudo>HiDpiIcon</kudo>
<kudo>ModernToolkit</kudo>
</kudos>
<update_contact>cawbird@ibboard.co.uk</update_contact>
<project_license>GPL-3.0+</project_license>
<developer_name>IBBoard</developer_name>
<url type="bugtracker">https://github.com/ibboard/cawbird/issues</url>
<url type="translate">https://www.transifex.com/cawbird/cawbird/</url>
<releases>
<release version="1.5" date="2022-03-18"><description>
<p>Building on the "look after yourself" message in v1.3 and the inclusive internationalisation in v1.4,
Cawbird 1.5 is being released in the context of the increasing importance of combatting disinformation
following Putin's atrocities in Ukraine.</p>
<p>New features:</p>
<ul>
<li>Cleanly and clearly handle "witheld" accounts, and hide witheld tweets (#428)</li>
<li>Added a button to "reload image" for any images that fail to load (#244)</li>
</ul>
<p>Fixes:</p>
<ul>
<li>Capture events so that "reload image" doesn't go to tweet view in single-click activation mode (#439)</li>
<li>Fix emoji chooser in non-English locales (thanks to @jtojnar)</li>
<li>Remove link to quoted tweet from timeline display (#406)</li>
<li>Support paging of blocked profiles so that users with lots of blocks don't see unwanted content, or get crashes on blocking</li>
<li>Fix overly long click zone for cropped images</li>
</ul>
<p>Improvements:</p>
<ul>
<li>Set `StartupNotify=true` in desktop file to improve desktop integration, especially on mobile (thanks to @AlexMitter)</li>
<li>Focus returns to the text input box after inserting an emoji (#427)</li>
<li>Update Danish, Dutch, Gaelic, Brazilian Portuguese and Spanish translations</li>
</ul>
<p>Developer:</p>
<ul>
<li>Don't assume that `~/.config` exists (thanks to @a-wai)</li>
<li>Use slashes in dconf path instead of dots (#402)</li>
<li>Updated Gnome runtime in Flatpak dev build</li>
</ul>
</description></release>
<release version="1.4.2" date="2021-09-19"><description>
<p>Cawbird 1.4.2 is a maintenance release with two crash fixes, an emoji fix and updated translations.</p>
<p>Fixes:</p>
<ul>
<li>Fixed crash when opening DMs if one of the DMs had entities defined out of order in the JSON (#391)</li>
<li>Fixed crash when first creating an account due to null account object (#399)</li>
<li>Alter emoji data checking to support changes with recent GTK 3.24 versions (#392)</li>
</ul>
<p>Improvements:</p>
<ul>
<li>Updated French and English translations</li>
</ul>
</description></release>
<release version="1.4.1" date="2021-05-08"><description>
<p>Hotfix to correct "Send" button state issues for direct messages</p>
</description></release>
<release version="1.4" date="2021-05-01"><description>
<p>It has been a while in the making, but Cawbird 1.4 adds lots of features and improves our internationalisation.</p>
<p>Fixes:</p>
<ul>
<li>Fixed repeat notifications due to message overlap (which we do to avoid missing messages!) (#292)</li>
<li>Fixed handling of links with ampersands in them (#305)</li>
<li>Fixed handling of Twitter video URLs with ampersands in them (#338)</li>
<li>Fixed cropping of tweets in timelines, particularly in narrow windows (#296)</li>
<li>Fixed handling of translations so that it works in environments like Flatpak (#297)</li>
</ul>
<p>Improvements:</p>
<ul>
<li>Added Normal/Large/X-Large/XX-Large text sizes (#33)</li>
<li>Added "Translate Content" option to tweets with option of using Google, Bing, DeepL or custom providers (#161)</li>
<li>Better counting of ZWJ emoji - Cawbird now passes Twitter's own compliance tests (#114)</li>
<li>Added Scottish Gaelic translations (thanks to @gaidheileamail1)</li>
<li>All strings in the UI are now translatable (#351, #362)</li>
<li>Add a confirmation to delete draft tweet on Cancel (#340)</li>
<li>Made threaded tweets more obvious by including "Reply to" line for self-reply threads in timeline (#339)</li>
<li>Tweets are now added to your timeline when you follow a user (and hidden when you unfollow them) (#19)</li>
<li>Improved rendering lag when focussing and unfocussing Cawbird (#204)</li>
<li>Improved spacing and alignment of images and added a border to define edges (#290, #306)</li>
<li>Added the ability to temporarily show a blocked or muted account (#299)</li>
<li>Reduced the size of the info icon for the image description notification to avoid it obscuring too much of the image (#294)</li>
<li>Swapped to using the 😀 smiley for emoji input rather than 🐧 to be consistent with other applications and platforms (#298)</li>
</ul>
<p>Developer:</p>
<ul>
<li>Make it easier to build Cawbird with custom Twitter secrets so that distro builds don't consume the new (June 2019) 100,000 requests per day per app limits (#310)</li>
<li>Added an option to use local translation files rather than the system ones, for debugging without installation</li>
<li>Added a `-Dmswindows=true` config flag to allow builds that work with Windows's broken "mimetypes are just file extensions" behaviour</li>
</ul>
</description></release>
<release version="1.3.2" date="2021-01-11"><description>
<p>Cawbird 1.3.2 is a maintenance release due to a privacy issue caused by third-party builds of Cawbird using "debug" builds.</p>
<p>Users of native distro packages and other packages that used release builds should not have been affected. We appologise for any inconvenience caused and continue to recommend that users use native packages where possible.</p>
<p>Fixes:</p>
<ul>
<li>Make it clearer to third-party packagers (e.g. Flatpak and Snap) when they are building debug builds instead of release builds, which log the plain text content of all tweets and DMs to the console, which is then captured in the system log (#274)</li>
<li>Make it possible to build Cawbird without GStreamer video support again (#273)</li>
</ul>
<p>Improvements:</p>
<ul>
<li>Swapped out `g_print` statements for `g_debug` and generally tidied up some debug logging (relates to #274)</li>
<li>Make videos open the browser when GStreamer support is disabled (related to #273)</li>
<li>Updated Russian translation (thanks to Даниил Пронин)</li>
</ul>
<p>Developer:</p>
<ul>
<li>Fixed intermittent crash of `inlinedownloader` tests</li>
</ul>
</description></release>
<release version="1.3.1" date="2021-01-03"><description>
<p>Cawbird 1.3.1 fixes several gaps in the block/mute behaviour so that your experience is controlled from the start, as well
as including some media upload and mobile fixes and improvements.</p>
<p>Fixes:</p>
<ul>
<li>Fix unblock and unmute wiping local cache of blocked/muted users</li>
<li>Load block/mute lists before downloading timeline/mentions to ensure we hide blocked/muted tweets at startup</li>
<li>Unblocking/unmuting now says "unblock" or "unmute" on the button instead of always saying "Unblock"</li>
<li>Fix media size checks so that videos don't fail because they're bigger than the image limit</li>
<li>Make a narrower user account list for narrow windows to avoid overflow and cropped "profile" button (#259)</li>
<li>Combine notification and tweet settings to allow narrower settings dialog for mobile</li>
</ul>
<p>Improvements:</p>
<ul>
<li>Hide all tweets in profile view when blocking/muting a user (we shouldn't assume people won't look at the profile)</li>
<li>Backfill progressively larger batches of tweets for profiles in case Disable RTs is hiding too many tweets so that the view doesn't scroll</li>
<li>Provide a tooltip message for why a media upload failed (e.g. Twitter doesn't support video codec)</li>
<li>Updated Dutch, Danish and Italian translations</li>
</ul>
</description></release>
<release version="1.3" date="2020-12-31"><description>
<p>Cawbird version 1.3 is the "look after yourself" edition. We've got lots of features and fixes, but there are several key improvements to
managing your interactions that should have been implemented/fixed sooner. Our priority is making Cawbird accessible and letting users
control their experience on Twitter.</p>
<p>Improvements:</p>
<ul>
<li>Apply filtering across all feeds (including search)</li>
<li>Apply changes to filtering, muting, blocking and hiding RTs across all feeds instantly</li>
<li>Allow the filtering of mentioned @-handles</li>
<li>Load media in DMs and linkify users and hashtags (#12)</li>
<li>Added ability to send media in DMs (#14)</li>
<li>Added ability to delete DMs (#7)</li>
<li>Load older DMs (#3)</li>
<li>Add ability to upload videos and larger animated GIFs (#248)</li>
<li>Use HTTPS avatars throughout</li>
</ul>
<p>Translations:</p>
<ul>
<li>Dutch and Danish (complete)</li>
<li>Italian and French (updated)</li>
</ul>
<p>Design changes:</p>
<ul>
<li>More accessible approach to loading "replied to" tweets (#164)</li>
<li>Improved user completion behaviour and interaction with user completion list</li>
<li>Added outline to media upload indicator to make it clearer on light images</li>
<li>Remove whitespace around tweets (e.g. when user has new lines and then a quoted URL or media that we're displaying)</li>
<li>Allow Compose view to shrink to narrower screens (e.g. for PinePhone) (#212)</li>
</ul>
<p>Fixes:</p>
<ul>
<li>Fix DM load order</li>
<li>Fix missing "reply" icon by providing our own (#208)</li>
<li>Fixed crashes when playing video (#123)</li>
<li>Avoid a crash when returned JSON is invalid (#200)</li>
<li>Fixed widget height calculations for responsive and non-responsive views (#202)</li>
<li>Fixed layout when starting in responsive width</li>
<li>Avoid an unnecessary request for tweets when loading timelines</li>
<li>Fixed completion query for known users</li>
<li>Fixed various run-time and compiler warnings</li>
<li>Fixed handling of command-line parameters (#246)</li>
</ul>
<p>Developer:</p>
<ul>
<li>Added "appdata" build config to allow building on platforms without AppStream (#35)</li>
<li>Changed Meson configuration and instructions to allow running dev version without installing</li>
</ul>
</description></release>
<release version="1.2.1" date="2020-09-20"><description>
<p>Changes in Cawbird 1.2.1:</p>
<p>Bug fixes:</p>
<ul>
<li>Fix crashes when images do not load correctly (#195)</li>
<li>Fix crashes when high-res image loads after dialog closes (#196) thanks to @lucaswerkmeister</li>
</ul>
<p>Improvements:</p>
<ul>
<li>Improve rendering of @-handles in mixed right-to-left/left-to-right text (#194)</li>
</ul>
</description></release>
<release version="1.2.0" date="2020-09-05"><description>
<p>Changes in Cawbird 1.2.0:</p>
<p>Improvements:</p>
<ul>
<li>Resolved major accessibility issue with timelines and improved other bits of accessibility by naming/describing widgets (#143)</li>
<li>Added ability to read descriptions on images (#11)</li>
<li>Added ability to add descriptions to images when posting (#10)</li>
<li>Reduced notifications when first logging in (#137)</li>
<li>Window can now be reduced to a narrower width and has a "responsive" layout for tweets (#57)</li>
<li>Reduce memory usage by loading smaller (600px) thumbnails and only loading images on demand (#142). Also reduces bandwidth use (especially with images disabled)</li>
<li>Let image sets loop back to start, and show progress through images (#172)</li>
<li>Made "Replying to" on Tweet info page list all users (including self-reply) so that it is more obvious when the tweet is part of a thread (#158)</li>
<li>Reworked @-mention completion so that it works with multilingual text</li>
<li>Adjust "media link removal" behaviour so that we still show the link when image loading is disabled so that users know there is media</li>
<li>Stopped shipping librest and started using system version</li>
<li>Made account removal less "scary" - now removes rather than deleting account</li>
<li>Improved consistency of progress status while searching</li>
<li>Updated Danish translation (thanks @mads5408) and Dutch translation (thanks @Vistaus) to 100% coverage</li>
</ul>
<p>Bug fixes:</p>
<ul>
<li>Update handling of top-level domains to resolve character counting mismatch (#64)</li>
<li>Handle repeated attachment of the same image with the same path (#34)</li>
<li>Fix scrolling back to older tweets in thread on some platforms (#164)</li>
<li>Fixed @-mention completion not handling underscores</li>
<li>Fixed a crash when removing the currently open account</li>
<li>Fixed a usability issue where removing an account with multiple other accounts available showed the "Add account" interface with no account selector instead of showing another account</li>
<li>Fixed show/hide bug for media in quoted tweets</li>
<li>Put other users's lists in the correct place (created or subscribed)</li>
<li>Fixed builds on platforms without an implicit `#include <string.h>`</li>
</ul>
</description></release>
<release version="1.1.0" date="2020-05-31"><description>
<p>Changes in Cawbird 1.1.0:</p>
<p>Improvements:</p>
<ul>
<li>Moved tweet replies below tweet in detailed view, so it now matches the layour of almost all other clients (#16)</li>
<li>Improved tweet threading (#17):
Now tries to build entire self-reply thread above *and* below the tweet;
Sorts all self-replies first, then mentioned replies, then other replies;
Shows more than five replies;
Added RT marker to detailed tweet view; and
Reduce number of requests to Twitter API when moving up and down a thread.
</li>
<li>Added overlap to timeline tweet fetching to significantly reduce the likelihood of missing tweets due to "eventual consistency" of Twitter servers (#147)</li>
<li>Updated Danish translation (thanks @mads5408) and Dutch translation (thanks @Vistaus) to 100% coverage and increased coverage of Arabic translation (thanks @Ammar_Khaled and @Raayib)</li>
</ul>
<p>Bug fixes:</p>
<ul>
<li>Links in direct messages remain clickable after closing and opening (#13)</li>
<li>Added support for updated GTK Emoji data (#148 - backported into official v1.0.5 builds)</li>
<li>Fixed an SQL error when trying to complete names in tweets</li>
</ul>
<p>UI changes:</p>
<ul>
<li>Hidden and deleted tweets in threads no longer trigger error dialogs (#138 and #153)</li>
<li>Timestamps on direct messages now update (#30)</li>
<li>Fix keyboard navigation in detailed tweet view (#145)</li>
<li>Debug builds can dump tweet JSON and details from Tweet Info page (#26)</li>
<li>List name is now shown as window title (#135)</li>
<li>List now uses actual title, not unique URL-name</li>
<li>List of lists now updates (with caching)</li>
<li>Tweets in searches now show like/favourite status</li>
<li>Added translation strings for new "limited reply" tweets</li>
<li>Handle "operation cancelled" 'error' so that users don't see a dialog when clicking back too quickly</li>
</ul>
</description></release>
<release version="1.0.5" date="2020-04-08"><description>
<p>Changes in Cawbird 1.0.5:</p>
<p>Improvements:</p>
<ul>
<li>Made Cawbird translatable through Transifex! (#47)</li>
<li>Added new Danish translation (thanks @mads5408), updated Catalan (thanks @joensgi), Dutch (thanks @Vistaus), and Italian (thanks @albanobattistella)</li>
<li>Improved image scaling to handle portrait monitors (#59)</li>
</ul>
<p>Bug fixes:</p>
<ul>
<li>Fixed parsing/display of some old tweets with bad encoding (#69)</li>
<li>Fixed URL encoding issues in user profiles breaking URL display (#78)</li>
<li>Removed case-sensitive filtering of @-handle in mentions so all mentions now show (#81)</li>
<li>Fixed segfault on CentOS 8 due to a bug in how RHEL/CentOS patch a glib function for FIPS compliance (#82)</li>
</ul>
<p>UI changes:</p>
<ul>
<li>Added dark mode toggle in settings (#67)</li>
<li>Improved error messages so that they're not just "Forbidden" or "Not Found" (#8, #41)</li>
<li>Protected accounts are now marked with a padlock (#18)</li>
<li>Made tweet timestamps into links to twitter.com (#129)</li>
<li>Added @-handle next to display name for retweets (#20)</li>
<li>Un-dimmed some labels to improve accessibility (#80)</li>
<li>Added tooltips for usernames, @-handles and Twitter client names (#87, #120)</li>
<li>DM composition area can now be resized (#72)</li>
<li>Tidied up CSS to remove warnings (#5)</li>
</ul>
</description></release>
<release version="1.0.4" date="2020-01-12"><description>
<p>Changes in Cawbird 1.0.4:</p>
<ul>
<li>Reduce bespoke themeing and make the main bar use native colours</li>
<li>Import favourited images from Corebird (if they exist)</li>
<li>Fixed crash caused by Twitter sending invalid entity positions in tweet</li>
<li>Fixed tweet length error with counting prime marks (quotes)</li>
<li>Update Italian translation (thanks to @albanobattistella)</li>
<li>Completed Flatpak build (thanks to @p1u3o)</li>
</ul>
</description></release>
<release version="1.0.3" date="2019-10-20"><description>
<p>Changes in Cawbird 1.0.3:</p>
<ul>
<li>Handle tweet media separatelty from quoted tweet media - now displays quote with image reply!</li>
<li>Fix silently handled tweet parsing errors from RT syncing changes</li>
<li>Tidy up README</li>
</ul>
</description></release>
<release version="1.0.2" date="2019-10-05"><description>
<p>Changes in Cawbird 1.0.2:</p>
<ul>
<li>Handle TLS errors that we're getting from Twitter and GnuTLS</li>
<li>Add initial Flatpak manifest (thanks to @p1u3o)</li>
<li>Keep retweet status in sync across pages</li>
<li>Fix building on newer versions of Vala (thanks to @lucaswerkmeister)</li>
<li>Make image click positioning behaviour consistent</li>
</ul>
</description></release>
<release version="1.0.1" date="2019-08-31"><description>
<p>Changes in Cawbird 1.0.1:</p>
<ul>
<li>Fix search with non-alphanumeric characters</li>
<li>Redesign logo in a Tango style</li>
<li>Migrates DMs, filters and snippets from old Corebird accounts</li>
</ul>
</description></release>
<release version="1.0" date="2019-08-04"><description>
<p>Changes in Cawbird 1.0:</p>
<ul>
<li>First release after forking from Corebird</li>
<li>Supports new non-streaming API</li>
<li>Incorporates UI tweaks and customisations</li>
<li>Fixes source links for New Twitter web interface changes</li>
</ul>
</description></release>
</releases>
<provides>
<binary>cawbird</binary>
</provides>
<requires>
<display_length compare="ge">320</display_length>
<display_length compare="ge">xsmall</display_length>
</requires>
<recommends>
<control>pointing</control>
<control>keyboard</control>
<!--
Note: We actually <supports> touch, but Gnome Software doesn't support that
until they implement https://gitlab.gnome.org/GNOME/gnome-software/-/issues/1774
-->
<control>touch</control>
</recommends>
<content_rating type="oars-1.1">
<content_attribute id="social-chat">moderate</content_attribute>
<content_attribute id="social-info">mild</content_attribute>
<content_attribute id="social-audio">moderate</content_attribute>
</content_rating>
<custom>
<value key="Purism::form_factor">workstation</value>
<value key="Purism::form_factor">mobile</value>
</custom>
</component>
================================================
FILE: data/uk.co.ibboard.cawbird.desktop.in
================================================
[Desktop Entry]
Name=Cawbird
GenericName=Twitter Client
Comment=Use Twitter from within a normal desktop application
# TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
Keywords=twitter;
Exec=cawbird
Type=Application
StartupNotify=true
# TRANSLATORS: Do NOT translate or transliterate this text (this is an icon file name)!
Icon=uk.co.ibboard.cawbird
Categories=Network;GTK;
DBusActivatable=true
StartupWMClass=cawbird
# TRANSLATORS: Do NOT translate or transliterate this text (these are enum types)!
X-Purism-FormFactor=Workstation;Mobile;
================================================
FILE: data/uk.co.ibboard.cawbird.gschema.xml
================================================
<schemalist>
<enum id="uk.co.ibboard.cawbird.tweet-stack">
<value nick="Never" value="0" />
<value nick="Every" value="1" />
<value nick="Stack 5" value="5" />
<value nick="Stack 10" value="10" />
<value nick="Stack 25" value="25" />
<value nick="Stack 50" value="50" />
</enum>
<enum id="uk.co.ibboard.cawbird.media-visibility">
<value nick="Show" value="1" />
<value nick="Hide" value="2" />
<value nick="Hide in Timeline" value="3" />
</enum>
<enum id="uk.co.ibboard.cawbird.tweet-scale">
<value nick="Normal" value="0" />
<value nick="Large" value="1" />
<value nick="X-Large" value="2" />
<value nick="XX-Large" value="3" />
</enum>
<enum id="uk.co.ibboard.cawbird.translation-service">
<value nick="Google" value="0" />
<value nick="Bing" value="1" />
<value nick="DeepL" value="2" />
<value nick="Custom" value="3" />
</enum>
<enum id="uk.co.ibboard.cawbird.shortcut-key">
<value nick="Alt" value="0" />
<value nick="Ctrl" value="1" />
<value nick="Shift" value="2" />
<value nick="Super" value="3" />
<value nick="Primary" value="4" />
</enum>
<schema id="uk.co.ibboard.cawbird.core">
<key name="use-dark-theme" type="b">
<default>false</default>
<summary>Specifies if Cawbird should request to use the dark variant of the gtk theme</summary>
<description></description>
</key>
<key name="new-tweets-notify" enum="uk.co.ibboard.cawbird.tweet-stack">
<default>"Never"</default>
<summary>If/when the user should be notified about new tweets</summary>
<description>
</description>
</key>
<key name="new-mentions-notify" type="b">
<default>true</default>
<summary>Whether the user should be notified when another user mentions them in a tweet</summary>
<description></description>
</key>
<key name="new-dms-notify" type="b">
<default>true</default>
<summary>Whether the user should be notified when another user writes them a direct message</summary>
<description></description>
</key>
<key name="startup-accounts" type="as">
<default>[""]</default>
<summary>List of accounts which will be opened when Cawbird is started.</summary>
<description></description>
</key>
<key name="auto-scroll-on-new-tweets" type="b">
<default>false</default>
</key>
<key name="sidebar-visible" type="b">
<default>true</default>
<summary>Whether to show the topbar or not</summary>
</key>
<key name="accel-compose-tweet" type="s">
<default>"<Control>T"</default>
<summary>The accelerator to press in order to bring the ComposeTweetWindow up.
Must be parseable with gtk_accelerator_parse
</summary>
</key>
<key name="accel-toggle-sidebar" type="s">
<default>"<Control><Shift>S"</default>
<summary>Accelerator to press in order to show/hide the sidebar</summary>
</key>
<key name="accel-show-settings" type="s">
<default>"<Control><Shift>P"</default>
<summary>Accelerator to show the settings window</summary>
</key>
<key name="accel-show-account-dialog" type="s">
<default>"<Control>P"</default>
<summary>Accelerator to show the account dialog</summary>
</key>
<key name="accel-show-account-list" type="s">
<default>"<Control>K"</default>
<summary>Accelerator to show the account list (popover)</summary>
</key>
<key name="window-geometry" type="a{s(iiii)}">
<default>{}</default>
<summary></summary>
</key>
<key name="settings-geometry" type="(iiii)">
<default>(0,0,500,300)</default>
<summary>Size and position of the settings dialog</summary>
</key>
<key type="s" name="consumer-key">
<default>""</default>
<summary>The application's oauth consumer key.</summary>
</key>
<key type="s" name="consumer-secret">
<default>""</default>
<summary>The application's oauth consumer secret</summary>
</key>
<key type="b" name="round-avatars">
<default>false</default>
</key>
<key type="b" name="double-click-activation">
<default>false</default>
<summary>Whether or not to use double-click activation in tweet timelines</summary>
</key>
<key type="u" name="text-transform-flags">
<default>1</default>
<summary>Bitfield for text transformations</summary>
</key>
<key type="b" name="hide-nsfw-content">
<default>true</default>
<summary>Whether to hide images marked as inappropriate by default or not</summary>
</key>
<key name="media-visibility" enum="uk.co.ibboard.cawbird.media-visibility">
<default>"Show"</default>
<summary>When to show media attached to tweets</summary>
</key>
<key name="tweet-scale" enum="uk.co.ibboard.cawbird.tweet-scale">
<default>"Normal"</default>
<summary>Scale factor for tweets in timelines</summary>
</key>
<key name="translation-service" enum="uk.co.ibboard.cawbird.translation-service">
<default>"Google"</default>
<summary>Translation website to use</summary>
</key>
<key type="s" name="custom-translation-service">
<default>""</default>
<summary>Custom translation service URL using {SOURCE_LANG} for the source language code, {TARGET_LANG} for the target language code and {CONTENT} for the URI encoded tweet content</summary>
</key>
<key name="shortcut-key" enum="uk.co.ibboard.cawbird.shortcut-key">
<default>"Alt"</default>
<summary>Key to use with 1…7/Left/Right for page switching</summary>
</key>
</schema>
<!--
We use an extended schema here to allow us to reload old values with the wrong (dotted) path
so that we can transfer them.
We can't just re-load the main schema because you can't `with_path()` a schema with a path.
However, it does mean that we have to use `with_path()` on the main load as well because otherwise
we lose change notifications because the key is in uk.co.ibboard.cawbird.core and not in
the uk.co.ibboard.cawbird schema.
https://gitlab.gnome.org/GNOME/glib/-/blob/96279325/gio/gsettings.c#L445
-->
<schema id="uk.co.ibboard.cawbird"
path="/uk/co/ibboard/cawbird/"
gettext-domain="cawbird"
extends="uk.co.ibboard.cawbird.core">
</schema>
</schemalist>
================================================
FILE: data/uk.co.ibboard.cawbird.service.in
================================================
[D-BUS Service]
Name=uk.co.ibboard.cawbird
Exec=@bindir@/cawbird --gapplication-service
================================================
FILE: examples/accountdialog.vala
================================================
void main (string[] args) {
Gtk.init (ref args);
Utils.load_custom_css ();
Settings.init ();
var acc = new Account (1337, "Some Screen Name", "Some Name");
var dialog = new AccountDialog (acc);
dialog.show_all ();
Gtk.main ();
}
================================================
FILE: examples/meson.build
================================================
executable('tweetstates',
'tweetstates.vala',
cb_resources,
dependencies: cb_dep,
vala_args: [
meson.source_root() + '/vapi/cawbird-internal.vapi',
'--gresources=' + meson.source_root() + '/cawbird.gresource.xml',
]
)
================================================
FILE: examples/tweetstates.vala
================================================
Cb.Tweet parse_tweet (string input) {
var parser = new Json.Parser ();
try {
parser.load_from_data (input);
} catch (Error e) {
error (e.message);
}
Cb.Tweet tweet = new Cb.Tweet ();
tweet.load_from_json (parser.get_root (), 0, new GLib.DateTime.now_local ());
return tweet;
}
void main (string[] args) {
Gtk.init (ref args);
Settings.init ();
Utils.load_custom_css ();
Utils.load_custom_icons ();
Utils.init_soup_session ();
Twitter.get ().init ();
var window = new Gtk.Window ();
window.delete_event.connect (() => {Gtk.main_quit (); return true; });
var list = new Gtk.ListBox ();
list.selection_mode = Gtk.SelectionMode.NONE;
var list2 = new Gtk.ListBox ();
list2.selection_mode = Gtk.SelectionMode.NONE;
var list3 = new Gtk.ListBox ();
list3.selection_mode = Gtk.SelectionMode.NONE;
var scroller = new Gtk.ScrolledWindow (null, null);
scroller.hscrollbar_policy = Gtk.PolicyType.NEVER;
var box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0);
box.homogeneous = true;
// Ensure types
new LazyMenuButton ();
var fake_acount = new Account (1337, "baedert", "Foo Bar Baedert");
{
// Normal tweet.
var tweet = parse_tweet (NORMAL_TWEET);
var row = new TweetListEntry (tweet, null, fake_acount);
list.add (row);
}
{
// Retweet
var tweet = parse_tweet (RETWEET);
var row = new TweetListEntry (tweet, null, fake_acount);
list.add (row);
}
{
// Normal, but with media attached
var tweet = parse_tweet (NORMAL_WITH_MEDIA);
var row = new TweetListEntry (tweet, null, fake_acount);
list.add (row);
}
{
// Normal quote
var tweet = parse_tweet (NORMAL_QUOTE);
var row = new TweetListEntry (tweet, null, fake_acount);
list.add (row);
}
{
// Quote with Media
var tweet = parse_tweet (QUOTE_WITH_MEDIA);
var row = new TweetListEntry (tweet, null, fake_acount);
list2.add (row);
}
{
// Retweet with media
var tweet = parse_tweet (RETWEET_WITH_MEDIA);
var row = new TweetListEntry (tweet, null, fake_acount);
list2.add (row);
}
{
// Empty (no text) tweet with media
var tweet = parse_tweet (EMPTY_TWEET_WITH_MEDIA);
var row = new TweetListEntry (tweet, null, fake_acount);
list.add (row);
}
{
// Retweet with media but no text
var tweet = parse_tweet (EMPTY_RETWEET_WITH_MEDIA);
var row = new TweetListEntry (tweet, null, fake_acount);
list3.add (row);
}
{
// Video + Thumbnail of that video, but should only show video
var tweet = parse_tweet (VIDEO_AND_THUMBNAIL);
var row = new TweetListEntry (tweet, null, fake_acount);
list3.add (row);
}
{
// Reply to ONE user.
var tweet = parse_tweet (REPLY);
var row = new TweetListEntry (tweet, null, fake_acount);
list3.add (row);
}
{
// Reply to TWO users.
var tweet = parse_tweet (REPLY_TO_TWO);
var row = new TweetListEntry (tweet, null, fake_acount);
list3.add (row);
}
{
// Reply to MORE users.
var tweet = parse_tweet (REPLY2);
var row = new TweetListEntry (tweet, null, fake_acount);
list3.add (row);
}
{
// Retweet of a tweet that replies to multiple users (2!)
var tweet = parse_tweet (REPLY3);
var row = new TweetListEntry (tweet, null, fake_acount);
list3.add (row);
}
list.set_size_request (500, -1);
list2.set_size_request (500, -1);
list2.set_size_request (500, -1);
box.add (list);
box.add (list2);
box.add (list3);
scroller.add (box);
window.add (scroller);
window.show_all ();
window.resize (1500, 900);
Gtk.main ();
}
const string NORMAL_TWEET =
"""
{
"created_at" : "Wed Aug 03 04:06:47 +0000 2016",
"id" : 760688337610997764,
"id_str" : "760688337610997764",
"text" : "My dick was already out BEFORE Harambe died.",
"truncated" : false,
"entities" : {
"hashtags" : [
],
"symbols" : [
],
"user_mentions" : [
],
"urls" : [
]
},
"source" : "<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter Web Client</a>",
"in_reply_to_status_id" : null,
"in_reply_to_status_id_str" : null,
"in_reply_to_user_id" : null,
"in_reply_to_user_id_str" : null,
"in_reply_to_screen_name" : null,
"user" : {
"id" : 21369740,
"id_str" : "21369740",
"name" : "Rob DenBleyker",
"screen_name" : "RobDenBleyker",
"location" : "Dallas",
"description" : "I'm not Rob Dyrdek. Don't follow me.",
"url" : "https://t.co/5jh1OQTAOO",
"entities" : {
"url" : {
"urls" : [
{
"url" : "https://t.co/5jh1OQTAOO",
"expanded_url" : "http://www.explosm.net",
"display_url" : "explosm.net",
"indices" : [
0,
23
]
}
]
},
"description" : {
"urls" : [
]
}
},
"protected" : false,
"followers_count" : 126455,
"friends_count" : 800,
"listed_count" : 1284,
"created_at" : "Fri Feb 20 03:26:24 +0000 2009",
"favourites_count" : 1452,
"utc_offset" : -18000,
"time_zone" : "Central Time (US & Canada)",
"geo_enabled" : true,
"verified" : false,
"statuses_count" : 8088,
"lang" : "en",
"contributors_enabled" : false,
"is_translator" : false,
"is_translation_enabled" : false,
"profile_background_color" : "49585E",
"profile_background_image_url" : "http://abs.twimg.com/images/themes/theme1/bg.png",
"profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme1/bg.png",
"profile_background_tile" : false,
"profile_image_url" : "http://pbs.twimg.com/profile_images/751256809873281024/-FuDkY2p_normal.jpg",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/751256809873281024/-FuDkY2p_normal.jpg",
"profile_link_color" : "0C90F5",
"profile_sidebar_border_color" : "C0DEED",
"profile_sidebar_fill_color" : "DDEEF6",
"profile_text_color" : "333333",
"profile_use_background_image" : false,
"has_extended_profile" : false,
"default_profile" : false,
"default_profile_image" : false,
"following" : true,
"follow_request_sent" : false,
"notifications" : false
},
"geo" : null,
"coordinates" : null,
"place" : null,
"contributors" : null,
"is_quote_status" : false,
"retweet_count" : 111,
"favorite_count" : 335,
"favorited" : false,
"retweeted" : false,
"lang" : "en"
}
""";
const string RETWEET =
"""
{
"created_at" : "Tue Aug 02 17:25:04 +0000 2016",
"id" : 760526843699007488,
"id_str" : "760526843699007488",
"text" : "RT @wilw: OH: \"All fucking dentists are in the pocket of big floss!\"",
"truncated" : false,
"entities" : {
"hashtags" : [
],
"symbols" : [
],
"user_mentions" : [
{
"screen_name" : "wilw",
"name" : "Wil Wheaton",
"id" : 1183041,
"id_str" : "1183041",
"indices" : [
3,
8
]
}
],
"urls" : [
]
},
"source" : "<a href=\"http://www.echofon.com/\" rel=\"nofollow\">Echofon</a>",
"in_reply_to_status_id" : null,
"in_reply_to_status_id_str" : null,
"in_reply_to_user_id" : null,
"in_reply_to_user_id_str" : null,
"in_reply_to_screen_name" : null,
"user" : {
"id" : 18948541,
"id_str" : "18948541",
"name" : "Seth MacFarlane",
"screen_name" : "SethMacFarlane",
"location" : "Los Angeles",
"description" : "The Official Twitter Page of Seth MacFarlane - new album No One Ever Tells You available now on iTunes https://t.co/gLePVn5Mho",
"url" : "https://t.co/o4miqWAHnW",
"entities" : {
"url" : {
"urls" : [
{
"url" : "https://t.co/o4miqWAHnW",
"expanded_url" : "http://www.facebook.com/pages/Seth-MacFarlane/14105972607?ref=ts",
"display_url" : "facebook.com/pages/Seth-Mac…",
"indices" : [
0,
23
]
}
]
},
"description" : {
"urls" : [
{
"url" : "https://t.co/gLePVn5Mho",
"expanded_url" : "http://itun.es/us/Vx9p-",
"display_url" : "itun.es/us/Vx9p-",
"indices" : [
103,
126
]
}
]
}
},
"protected" : false,
"followers_count" : 10520286,
"friends_count" : 377,
"listed_count" : 0,
"created_at" : "Tue Jan 13 19:04:37 +0000 2009",
"favourites_count" : 0,
"utc_offset" : -25200,
"time_zone" : "Pacific Time (US & Canada)",
"geo_enabled" : false,
"verified" : true,
"statuses_count" : 5847,
"lang" : "en",
"contributors_enabled" : false,
"is_translator" : false,
"is_translation_enabled" : true,
"profile_background_color" : "C0DEED",
"profile_background_image_url" : "http://abs.twimg.com/images/themes/theme1/bg.png",
"profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme1/bg.png",
"profile_background_tile" : false,
"profile_image_url" : "http://pbs.twimg.com/profile_images/477598819715395585/g0lGqC_J_normal.jpeg",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/477598819715395585/g0lGqC_J_normal.jpeg",
"profile_link_color" : "0084B4",
"profile_sidebar_border_color" : "C0DEED",
"profile_sidebar_fill_color" : "DDEEF6",
"profile_text_color" : "333333",
"profile_use_background_image" : true,
"has_extended_profile" : false,
"default_profile" : true,
"default_profile_image" : false,
"following" : true,
"follow_request_sent" : false,
"notifications" : false
},
"geo" : null,
"coordinates" : null,
"place" : null,
"contributors" : null,
"retweeted_status" : {
"created_at" : "Tue Aug 02 17:18:45 +0000 2016",
"id" : 760525254489890818,
"id_str" : "760525254489890818",
"text" : "OH: \"All fucking dentists are in the pocket of big floss!\"",
"truncated" : false,
"entities" : {
"hashtags" : [
],
"symbols" : [
],
"user_mentions" : [
],
"urls" : [
]
},
"source" : "<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter Web Client</a>",
"in_reply_to_status_id" : null,
"in_reply_to_status_id_str" : null,
"in_reply_to_user_id" : null,
"in_reply_to_user_id_str" : null,
"in_reply_to_screen_name" : null,
"user" : {
"id" : 1183041,
"id_str" : "1183041",
"name" : "Wil Wheaton",
"screen_name" : "wilw",
"location" : "Los Angeles",
"description" : "Barrelslayer. Time Lord. Fake geek girl. On a good day I am charming as fuck.",
"url" : "http://t.co/UAYYOhbijM",
"entities" : {
"url" : {
"urls" : [
{
"url" : "http://t.co/UAYYOhbijM",
"expanded_url" : "http://wilwheaton.net/2009/02/what-to-expect-if-you-follow-me-on-twitter-or-how-im-going-to-disappoint-you-in-6-quick-steps/",
"display_url" : "wilwheaton.net/2009/02/what-t…",
"indices" : [
0,
22
]
}
]
},
"description" : {
"urls" : [
]
}
},
"protected" : false,
"followers_count" : 3050329,
"friends_count" : 355,
"listed_count" : 39190,
"created_at" : "Wed Mar 14 21:25:33 +0000 2007",
"favourites_count" : 557,
"utc_offset" : -25200,
"time_zone" : "Pacific Time (US & Canada)",
"geo_enabled" : false,
"verified" : true,
"statuses_count" : 65696,
"lang" : "en",
"contributors_enabled" : false,
"is_translator" : false,
"is_translation_enabled" : false,
"profile_background_color" : "022330",
"profile_background_image_url" : "http://pbs.twimg.com/profile_background_images/871683408/62c85b46792dfe6bfd16420b71646cdb.png",
"profile_background_image_url_https" : "https://pbs.twimg.com/profile_background_images/871683408/62c85b46792dfe6bfd16420b71646cdb.png",
"profile_background_tile" : true,
"profile_image_url" : "http://pbs.twimg.com/profile_images/660891140418236416/7zeCwT9K_normal.png",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/660891140418236416/7zeCwT9K_normal.png",
"profile_banner_url" : "https://pbs.twimg.com/profile_banners/1183041/1368668860",
"profile_link_color" : "F6101E",
"profile_sidebar_border_color" : "000000",
"profile_sidebar_fill_color" : "C0DFEC",
"profile_text_color" : "333333",
"profile_use_background_image" : true,
"has_extended_profile" : true,
"default_profile" : false,
"default_profile_image" : false,
"following" : false,
"follow_request_sent" : false,
"notifications" : false
},
"geo" : null,
"coordinates" : null,
"place" : null,
"contributors" : null,
"is_quote_status" : false,
"retweet_count" : 249,
"favorite_count" : 1418,
"favorited" : false,
"retweeted" : false,
"lang" : "en"
},
"is_quote_status" : false,
"retweet_count" : 249,
"favorite_count" : 0,
"favorited" : false,
"retweeted" : false,
"lang" : "en"
}
""";
const string NORMAL_WITH_MEDIA =
"""
{
"created_at" : "Wed Aug 03 11:18:39 +0000 2016",
"id" : 760797019908739072,
"id_str" : "760797019908739072",
"text" : "Someone went and ruined the last fun thing we had left https://t.co/a9Fc65NpIn",
"truncated" : false,
"entities" : {
"hashtags" : [
],
"symbols" : [
],
"user_mentions" : [
],
"urls" : [
],
"media" : [
{
"id" : 760796983409901568,
"id_str" : "760796983409901568",
"indices" : [
55,
78
],
"media_url" : "http://pbs.twimg.com/media/Co7k01ZWAAAO7XA.jpg",
"media_url_https" : "https://pbs.twimg.com/media/Co7k01ZWAAAO7XA.jpg",
"url" : "https://t.co/a9Fc65NpIn",
"display_url" : "pic.twitter.com/a9Fc65NpIn",
"expanded_url" : "http://twitter.com/internetofshit/status/760797019908739072/photo/1",
"type" : "photo",
"sizes" : {
"medium" : {
"w" : 1200,
"h" : 646,
"resize" : "fit"
},
"small" : {
"w" : 680,
"h" : 366,
"resize" : "fit"
},
"large" : {
"w" : 1972,
"h" : 1062,
"resize" : "fit"
},
"thumb" : {
"w" : 150,
"h" : 150,
"resize" : "crop"
}
}
}
]
},
"extended_entities" : {
"media" : [
{
"id" : 760796983409901568,
"id_str" : "760796983409901568",
"indices" : [
55,
78
],
"media_url" : "http://pbs.twimg.com/media/Co7k01ZWAAAO7XA.jpg",
"media_url_https" : "https://pbs.twimg.com/media/Co7k01ZWAAAO7XA.jpg",
"url" : "https://t.co/a9Fc65NpIn",
"display_url" : "pic.twitter.com/a9Fc65NpIn",
"expanded_url" : "http://twitter.com/internetofshit/status/760797019908739072/photo/1",
"type" : "photo",
"sizes" : {
"medium" : {
"w" : 1200,
"h" : 646,
"resize" : "fit"
},
"small" : {
"w" : 680,
"h" : 366,
"resize" : "fit"
},
"large" : {
"w" : 1972,
"h" : 1062,
"resize" : "fit"
},
"thumb" : {
"w" : 150,
"h" : 150,
"resize" : "crop"
}
}
}
]
},
"source" : "<a href=\"https://about.twitter.com/products/tweetdeck\" rel=\"nofollow\">TweetDeck</a>",
"in_reply_to_status_id" : null,
"in_reply_to_status_id_str" : null,
"in_reply_to_user_id" : null,
"in_reply_to_user_id_str" : null,
"in_reply_to_screen_name" : null,
"user" : {
"id" : 3356531254,
"id_str" : "3356531254",
"name" : "Internet of Shit",
"screen_name" : "internetofshit",
"location" : "In your stuff",
"description" : "Obviously the best thing to do is put a chip in it. Tips: internetofshit@gmail.com / Also on FB: https://t.co/VhThiGNgOo",
"url" : null,
"entities" : {
"description" : {
"urls" : [
{
"url" : "https://t.co/VhThiGNgOo",
"expanded_url" : "https://www.facebook.com/internetofshit",
"display_url" : "facebook.com/internetofshit",
"indices" : [
97,
120
]
}
]
}
},
"protected" : false,
"followers_count" : 126017,
"friends_count" : 92,
"listed_count" : 1630,
"created_at" : "Fri Jul 03 09:04:06 +0000 2015",
"favourites_count" : 2190,
"utc_offset" : -25200,
"time_zone" : "Pacific Time (US & Canada)",
"geo_enabled" : true,
"verified" : false,
"statuses_count" : 2254,
"lang" : "en",
"contributors_enabled" : false,
"is_translator" : false,
"is_translation_enabled" : false,
"profile_background_color" : "C0DEED",
"profile_background_image_url" : "http://abs.twimg.com/images/themes/theme1/bg.png",
"profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme1/bg.png",
"profile_background_tile" : false,
"profile_image_url" : "http://pbs.twimg.com/profile_images/616895706150797312/ol4PeiHz_normal.png",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/616895706150797312/ol4PeiHz_normal.png",
"profile_link_color" : "0084B4",
"profile_sidebar_border_color" : "C0DEED",
"profile_sidebar_fill_color" : "DDEEF6",
"profile_text_color" : "333333",
"profile_use_background_image" : true,
"has_extended_profile" : false,
"default_profile" : true,
"default_profile_image" : false,
"following" : true,
"follow_request_sent" : false,
"notifications" : false
},
"geo" : null,
"coordinates" : null,
"place" : null,
"contributors" : null,
"is_quote_status" : false,
"retweet_count" : 103,
"favorite_count" : 84,
"favorited" : false,
"retweeted" : false,
"possibly_sensitive" : false,
"possibly_sensitive_appealable" : false,
"lang" : "en"
}
""";
const string NORMAL_QUOTE =
"""
{
"created_at" : "Wed Aug 03 07:15:48 +0000 2016",
"id" : 760735908287119360,
"id_str" : "760735908287119360",
"text" : "Gute Nachrichten zum Morgen: @EMMUREmusic haben die Aufnahmen zu ihrem neuen Album abgeschlossen! https://t.co/zGwh0FXMJi",
"truncated" : false,
"entities" : {
"hashtags" : [
],
"symbols" : [
],
"user_mentions" : [
{
"screen_name" : "EMMUREmusic",
"name" : "EMMURE",
"id" : 42820699,
"id_str" : "42820699",
"indices" : [
29,
41
]
}
],
"urls" : [
{
"url" : "https://t.co/zGwh0FXMJi",
"expanded_url" : "https://twitter.com/FrankiePalmeri/status/760334690737790976",
"display_url" : "twitter.com/FrankiePalmeri…",
"indices" : [
98,
121
]
}
]
},
"source" : "<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter Web Client</a>",
"in_reply_to_status_id" : null,
"in_reply_to_status_id_str" : null,
"in_reply_to_user_id" : null,
"in_reply_to_user_id_str" : null,
"in_reply_to_screen_name" : null,
"user" : {
"id" : 51725030,
"id_str" : "51725030",
"name" : "impericon_de",
"screen_name" : "impericon_de",
"location" : "Leipzig/ Germany",
"description" : "check out http://t.co/RbUklLeWkv for further information",
"url" : "http://t.co/RbUklLeWkv",
"entities" : {
"url" : {
"urls" : [
{
"url" : "http://t.co/RbUklLeWkv",
"expanded_url" : "http://www.impericon.com",
"display_url" : "impericon.com",
"indices" : [
0,
22
]
}
]
},
"description" : {
"urls" : [
{
"url" : "http://t.co/RbUklLeWkv",
"expanded_url" : "http://www.impericon.com",
"display_url" : "impericon.com",
"indices" : [
10,
32
]
}
]
}
},
"protected" : false,
"followers_count" : 8077,
"friends_count" : 1226,
"listed_count" : 46,
"created_at" : "Sun Jun 28 13:07:50 +0000 2009",
"favourites_count" : 2657,
"utc_offset" : 7200,
"time_zone" : "Berlin",
"geo_enabled" : true,
"verified" : false,
"statuses_count" : 17025,
"lang" : "de",
"contributors_enabled" : false,
"is_translator" : false,
"is_translation_enabled" : false,
"profile_background_color" : "611222",
"profile_background_image_url" : "http://pbs.twimg.com/profile_background_images/868968985/73b34a4e0d724f8c8f61c06d76dcf925.jpeg",
"profile_background_image_url_https" : "https://pbs.twimg.com/profile_background_images/868968985/73b34a4e0d724f8c8f61c06d76dcf925.jpeg",
"profile_background_tile" : true,
"profile_image_url" : "http://pbs.twimg.com/profile_images/1374777540/ic_germany_normal.png",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/1374777540/ic_germany_normal.png",
"profile_banner_url" : "https://pbs.twimg.com/profile_banners/51725030/1470217813",
"profile_link_color" : "611222",
"profile_sidebar_border_color" : "000000",
"profile_sidebar_fill_color" : "DDFFCC",
"profile_text_color" : "333333",
"profile_use_background_image" : true,
"has_extended_profile" : false,
"default_profile" : false,
"default_profile_image" : false,
"following" : true,
"follow_request_sent" : false,
"notifications" : false
},
"geo" : null,
"coordinates" : null,
"place" : null,
"contributors" : null,
"is_quote_status" : true,
"quoted_status_id" : 760334690737790976,
"quoted_status_id_str" : "760334690737790976",
"quoted_status" : {
"created_at" : "Tue Aug 02 04:41:31 +0000 2016",
"id" : 760334690737790976,
"id_str" : "760334690737790976",
"text" : "Finished tracking the record. 🖒",
"truncated" : false,
"entities" : {
"hashtags" : [
],
"symbols" : [
],
"user_mentions" : [
],
"urls" : [
]
},
"source" : "<a href=\"http://twitter.com/download/android\" rel=\"nofollow\">Twitter for Android</a>",
"in_reply_to_status_id" : null,
"in_reply_to_status_id_str" : null,
"in_reply_to_user_id" : null,
"in_reply_to_user_id_str" : null,
"in_reply_to_screen_name" : null,
"user" : {
"id" : 208089519,
"id_str" : "208089519",
"name" : "⛧",
"screen_name" : "FrankiePalmeri",
"location" : "World Warrior ",
"description" : "シャドルー Best known as the singer of @EMMUREmusic\nFor booking/features-GodOfRue@Gmail.com\n#MVC2",
"url" : null,
"entities" : {
"description" : {
"urls" : [
]
}
},
"protected" : false,
"followers_count" : 6843,
"friends_count" : 0,
"listed_count" : 17,
"created_at" : "Tue Oct 26 16:20:47 +0000 2010",
"favourites_count" : 6444,
"utc_offset" : -18000,
"time_zone" : "Central Time (US & Canada)",
"geo_enabled" : true,
"verified" : true,
"statuses_count" : 7346,
"lang" : "en",
"contributors_enabled" : false,
"is_translator" : false,
"is_translation_enabled" : false,
"profile_background_color" : "C0DEED",
"profile_background_image_url" : "http://abs.twimg.com/images/themes/theme1/bg.png",
"profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme1/bg.png",
"profile_background_tile" : false,
"profile_image_url" : "http://pbs.twimg.com/profile_images/744425940789276672/qOmnwRUv_normal.jpg",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/744425940789276672/qOmnwRUv_normal.jpg",
"profile_banner_url" : "https://pbs.twimg.com/profile_banners/208089519/1466846528",
"profile_link_color" : "0084B4",
"profile_sidebar_border_color" : "C0DEED",
"profile_sidebar_fill_color" : "DDEEF6",
"profile_text_color" : "333333",
"profile_use_background_image" : true,
"has_extended_profile" : false,
"default_profile" : true,
"default_profile_image" : false,
"following" : false,
"follow_request_sent" : false,
"notifications" : false
},
"geo" : null,
"coordinates" : null,
"place" : {
"id" : "3b77caf94bfc81fe",
"url" : "https://api.twitter.com/1.1/geo/id/3b77caf94bfc81fe.json",
"place_type" : "city",
"name" : "Los Angeles",
"full_name" : "Los Angeles, CA",
"country_code" : "US",
"country" : "United States",
"contained_within" : [
],
"bounding_box" : {
"type" : "Polygon",
"coordinates" : [
[
[
-118.668404,
33.704537999999999
],
[
-118.15540900000001,
33.704537999999999
],
[
-118.15540900000001,
34.337040999999999
],
[
-118.668404,
34.337040999999999
]
]
]
},
"attributes" : {
}
},
"contributors" : null,
"is_quote_status" : false,
"retweet_count" : 38,
"favorite_count" : 136,
"favorited" : false,
"retweeted" : false,
"lang" : "en"
},
"retweet_count" : 1,
"favorite_count" : 7,
"favorited" : false,
"retweeted" : false,
"possibly_sensitive" : false,
"possibly_sensitive_appealable" : false,
"lang" : "de"
}
""";
const string QUOTE_WITH_MEDIA =
"""
{
"created_at" : "Wed Aug 03 09:48:12 +0000 2016",
"id" : 760774260315004928,
"id_str" : "760774260315004928",
"text" : "Wir sind am Wochenende übrigens wieder beim Wacken Open Air am Start - wer noch? https://t.co/xEEtAO37jF",
"truncated" : false,
"entities" : {
"hashtags" : [
],
"symbols" : [
],
"user_mentions" : [
],
"urls" : [
{
"url" : "https://t.co/xEEtAO37jF",
"expanded_url" : "https://twitter.com/Wacken/status/760774020631556096",
"display_url" : "twitter.com/Wacken/status/…",
"indices" : [
81,
104
]
}
]
},
"source" : "<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter Web Client</a>",
"in_reply_to_status_id" : null,
"in_reply_to_status_id_str" : null,
"in_reply_to_user_id" : null,
"in_reply_to_user_id_str" : null,
"in_reply_to_screen_name" : null,
"user" : {
"id" : 51725030,
"id_str" : "51725030",
"name" : "impericon_de",
"screen_name" : "impericon_de",
"location" : "Leipzig/ Germany",
"description" : "check out http://t.co/RbUklLeWkv for further information",
"url" : "http://t.co/RbUklLeWkv",
"entities" : {
"url" : {
"urls" : [
{
"url" : "http://t.co/RbUklLeWkv",
"expanded_url" : "http://www.impericon.com",
"display_url" : "impericon.com",
"indices" : [
0,
22
]
}
]
},
"description" : {
"urls" : [
{
"url" : "http://t.co/RbUklLeWkv",
"expanded_url" : "http://www.impericon.com",
"display_url" : "impericon.com",
"indices" : [
10,
32
]
}
]
}
},
"protected" : false,
"followers_count" : 8077,
"friends_count" : 1226,
"listed_count" : 46,
"created_at" : "Sun Jun 28 13:07:50 +0000 2009",
"favourites_count" : 2657,
"utc_offset" : 7200,
"time_zone" : "Berlin",
"geo_enabled" : true,
"verified" : false,
"statuses_count" : 17025,
"lang" : "de",
"contributors_enabled" : false,
"is_translator" : false,
"is_translation_enabled" : false,
"profile_background_color" : "611222",
"profile_background_image_url" : "http://pbs.twimg.com/profile_background_images/868968985/73b34a4e0d724f8c8f61c06d76dcf925.jpeg",
"profile_background_image_url_https" : "https://pbs.twimg.com/profile_background_images/868968985/73b34a4e0d724f8c8f61c06d76dcf925.jpeg",
"profile_background_tile" : true,
"profile_image_url" : "http://pbs.twimg.com/profile_images/1374777540/ic_germany_normal.png",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/1374777540/ic_germany_normal.png",
"profile_banner_url" : "https://pbs.twimg.com/profile_banners/51725030/1470217813",
"profile_link_color" : "611222",
"profile_sidebar_border_color" : "000000",
"profile_sidebar_fill_color" : "DDFFCC",
"profile_text_color" : "333333",
"profile_use_background_image" : true,
"has_extended_profile" : false,
"default_profile" : false,
"default_profile_image" : false,
"following" : true,
"follow_request_sent" : false,
"notifications" : false
},
"geo" : null,
"coordinates" : null,
"place" : null,
"contributors" : null,
"is_quote_status" : true,
"quoted_status_id" : 760774020631556096,
"quoted_status_id_str" : "760774020631556096",
"quoted_status" : {
"created_at" : "Wed Aug 03 09:47:15 +0000 2016",
"id" : 760774020631556096,
"id_str" : "760774020631556096",
"text" : "Business as usual. Work on main stages continues. All is well. #Wacken https://t.co/6oNpNgSFmx",
"truncated" : false,
"entities" : {
"hashtags" : [
{
"text" : "Wacken",
"indices" : [
64,
71
]
}
],
"symbols" : [
],
"user_mentions" : [
],
"urls" : [
],
"media" : [
{
"id" : 760773998955421696,
"id_str" : "760773998955421696",
"indices" : [
72,
95
],
"media_url" : "http://pbs.twimg.com/media/Co7P69oXYAAcTYR.jpg",
"media_url_https" : "https://pbs.twimg.com/media/Co7P69oXYAAcTYR.jpg",
"url" : "https://t.co/6oNpNgSFmx",
"display_url" : "pic.twitter.com/6oNpNgSFmx",
"expanded_url" : "http://twitter.com/Wacken/status/760774020631556096/photo/1",
"type" : "photo",
"sizes" : {
"medium" : {
"w" : 1200,
"h" : 675,
"resize" : "fit"
},
"small" : {
"w" : 680,
"h" : 383,
"resize" : "fit"
},
"large" : {
"w" : 2048,
"h" : 1152,
"resize" : "fit"
},
"thumb" : {
"w" : 150,
"h" : 150,
"resize" : "crop"
}
}
}
]
},
"extended_entities" : {
"media" : [
{
"id" : 760773998955421696,
"id_str" : "760773998955421696",
"indices" : [
72,
95
],
"media_url" : "http://pbs.twimg.com/media/Co7P69oXYAAcTYR.jpg",
"media_url_https" : "https://pbs.twimg.com/media/Co7P69oXYAAcTYR.jpg",
"url" : "https://t.co/6oNpNgSFmx",
"display_url" : "pic.twitter.com/6oNpNgSFmx",
"expanded_url" : "http://twitter.com/Wacken/status/760774020631556096/photo/1",
"type" : "photo",
"sizes" : {
"medium" : {
"w" : 1200,
"h" : 675,
"resize" : "fit"
},
"small" : {
"w" : 680,
"h" : 383,
"resize" : "fit"
},
"large" : {
"w" : 2048,
"h" : 1152,
"resize" : "fit"
},
"thumb" : {
"w" : 150,
"h" : 150,
"resize" : "crop"
}
}
}
]
},
"source" : "<a href=\"http://twitter.com/download/android\" rel=\"nofollow\">Twitter for Android</a>",
"in_reply_to_status_id" : null,
"in_reply_to_status_id_str" : null,
"in_reply_to_user_id" : null,
"in_reply_to_user_id_str" : null,
"in_reply_to_screen_name" : null,
"user" : {
"id" : 15475088,
"id_str" : "15475088",
"name" : "Wacken Open Air",
"screen_name" : "Wacken",
"location" : "Wacken, Germany",
"description" : "Welcome to the official W:O:A Twitter account! Impressum: https://t.co/0Nvmi1UOVI",
"url" : "http://t.co/eklJ4O4IqD",
"entities" : {
"url" : {
"urls" : [
{
"url" : "http://t.co/eklJ4O4IqD",
"expanded_url" : "http://www.wacken.com/",
"display_url" : "wacken.com",
"indices" : [
0,
22
]
}
]
},
"description" : {
"urls" : [
{
"url" : "https://t.co/0Nvmi1UOVI",
"expanded_url" : "http://bit.ly/1xx5ODO",
"display_url" : "bit.ly/1xx5ODO",
"indices" : [
60,
83
]
}
]
}
},
"protected" : false,
"followers_count" : 61074,
"friends_count" : 259,
"listed_count" : 602,
"created_at" : "Thu Jul 17 22:46:52 +0000 2008",
"favourites_count" : 314,
"utc_offset" : 7200,
"time_zone" : "Ljubljana",
"geo_enabled" : true,
"verified" : false,
"statuses_count" : 3660,
"lang" : "de",
"contributors_enabled" : false,
"is_translator" : false,
"is_translation_enabled" : false,
"profile_background_color" : "000000",
"profile_background_image_url" : "http://pbs.twimg.com/profile_background_images/436070844293345280/3EWufvsr.jpeg",
"profile_background_image_url_https" : "https://pbs.twimg.com/profile_background_images/436070844293345280/3EWufvsr.jpeg",
"profile_background_tile" : false,
"profile_image_url" : "http://pbs.twimg.com/profile_images/627856569699598340/OsQ1UOLl_normal.png",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/627856569699598340/OsQ1UOLl_normal.png",
"profile_banner_url" : "https://pbs.twimg.com/profile_banners/15475088/1438527965",
"profile_link_color" : "5BD006",
"profile_sidebar_border_color" : "000000",
"profile_sidebar_fill_color" : "EFEFEF",
"profile_text_color" : "333333",
"profile_use_background_image" : true,
"has_extended_profile" : false,
"default_profile" : false,
"default_profile_image" : false,
"following" : false,
"follow_request_sent" : false,
"notifications" : false
},
"geo" : null,
"coordinates" : null,
"place" : {
"id" : "b442982971a0c2b5",
"url" : "https://api.twitter.com/1.1/geo/id/b442982971a0c2b5.json",
"place_type" : "city",
"name" : "Wacken",
"full_name" : "Wacken, Deutschland",
"country_code" : "DE",
"country" : "Germany",
"contained_within" : [
],
"bounding_box" : {
"type" : "Polygon",
"coordinates" : [
[
[
9.3435539999999992,
54.009207000000004
],
[
9.4074019999999994,
54.009207000000004
],
[
9.4074019999999994,
54.038155000000003
],
[
9.3435539999999992,
54.038155000000003
]
]
]
},
"attributes" : {
}
},
"contributors" : null,
"is_quote_status" : false,
"retweet_count" : 7,
"favorite_count" : 15,
"favorited" : false,
"retweeted" : false,
"possibly_sensitive" : false,
"possibly_sensitive_appealable" : false,
"lang" : "en"
},
"retweet_count" : 0,
"favorite_count" : 0,
"favorited" : false,
"retweeted" : false,
"possibly_sensitive" : false,
"possibly_sensitive_appealable" : false,
"lang" : "de"
}
""";
const string RETWEET_WITH_MEDIA =
"""
{
"created_at" : "Wed Aug 03 01:22:42 +0000 2016",
"id" : 760647046835544064,
"id_str" : "760647046835544064",
"text" : "RT @shutupmikeginn: Hey @ScottAdamsSays, @eedrk & I are big fans so we recut Dilbert to deal with contemporary social issues! Please RT! ht…",
"truncated" : false,
"entities" : {
"hashtags" : [
],
"symbols" : [
],
"user_mentions" : [
{
"screen_name" : "shutupmikeginn",
"name" : "shut up, mike",
"id" : 246394886,
"id_str" : "246394886",
"indices" : [
3,
18
]
},
{
"screen_name" : "ScottAdamsSays",
"name" : "Scott Adams",
"id" : 2853461537,
"id_str" : "2853461537",
"indices" : [
24,
39
]
},
{
"screen_name" : "eedrk",
"name" : "derek",
"id" : 1350600582,
"id_str" : "1350600582",
"indices" : [
41,
47
]
}
],
"urls" : [
],
"media" : [
{
"id" : 760627464456462336,
"id_str" : "760627464456462336",
"indices" : [
143,
144
],
"media_url" : "http://pbs.twimg.com/ext_tw_video_thumb/760627464456462336/pu/img/ZmNeZzX7qcwzsuon.jpg",
"media_url_https" : "https://pbs.twimg.com/ext_tw_video_thumb/760627464456462336/pu/img/ZmNeZzX7qcwzsuon.jpg",
"url" : "https://t.co/Dth5YBHXeu",
"display_url" : "pic.twitter.com/Dth5YBHXeu",
"expanded_url" : "http://twitter.com/shutupmikeginn/status/760628917837312000/video/1",
"type" : "photo",
"sizes" : {
"medium" : {
"w" : 600,
"h" : 411,
"resize" : "fit"
},
"thumb" : {
"w" : 150,
"h" : 150,
"resize" : "crop"
},
"large" : {
"w" : 700,
"h" : 480,
"resize" : "fit"
},
"small" : {
"w" : 340,
"h" : 233,
"resize" : "fit"
}
},
"source_status_id" : 760628917837312000,
"source_status_id_str" : "760628917837312000",
"source_user_id" : 246394886,
"source_user_id_str" : "246394886"
}
]
},
"extended_entities" : {
"media" : [
{
"id" : 760627464456462336,
"id_str" : "760627464456462336",
"indices" : [
143,
144
],
"media_url" : "http://pbs.twimg.com/ext_tw_video_thumb/760627464456462336/pu/img/ZmNeZzX7qcwzsuon.jpg",
"media_url_https" : "https://pbs.twimg.com/ext_tw_video_thumb/760627464456462336/pu/img/ZmNeZzX7qcwzsuon.jpg",
"url" : "https://t.co/Dth5YBHXeu",
"display_url" : "pic.twitter.com/Dth5YBHXeu",
"expanded_url" : "http://twitter.com/shutupmikeginn/status/760628917837312000/video/1",
"type" : "video",
"sizes" : {
"medium" : {
"w" : 600,
"h" : 411,
"resize" : "fit"
},
"thumb" : {
"w" : 150,
"h" : 150,
"resize" : "crop"
},
"large" : {
"w" : 700,
"h" : 480,
"resize" : "fit"
},
"small" : {
"w" : 340,
"h" : 233,
"resize" : "fit"
}
},
"source_status_id" : 760628917837312000,
"source_status_id_str" : "760628917837312000",
"source_user_id" : 246394886,
"source_user_id_str" : "246394886",
"video_info" : {
"aspect_ratio" : [
35,
24
],
"duration_millis" : 50017,
"variants" : [
{
"content_type" : "application/dash+xml",
"url" : "https://video.twimg.com/ext_tw_video/760627464456462336/pu/pl/WgyGZ2bR67CZKbIe.mpd"
},
{
"bitrate" : 320000,
"content_type" : "video/mp4",
"url" : "https://video.twimg.com/ext_tw_video/760627464456462336/pu/vid/262x180/bMwQb2LGoymiuNBF.mp4"
},
{
"content_type" : "application/x-mpegURL",
"url" : "https://video.twimg.com/ext_tw_video/760627464456462336/pu/pl/WgyGZ2bR67CZKbIe.m3u8"
},
{
"bitrate" : 832000,
"content_type" : "video/mp4",
"url" : "https://video.twimg.com/ext_tw_video/760627464456462336/pu/vid/524x360/akoT29AzRB-K7Tvf.mp4"
}
]
},
"additional_media_info" : {
"monetizable" : false,
"source_user" : {
"id" : 246394886,
"id_str" : "246394886",
"name" : "shut up, mike",
"screen_name" : "shutupmikeginn",
"location" : "Los Angeles, CA",
"description" : "writer (left handed) // shutupmikeginn @ gmail . com // @midnight",
"url" : "https://t.co/JLpcO66Txj",
"entities" : {
"url" : {
"urls" : [
{
"url" : "https://t.co/JLpcO66Txj",
"expanded_url" : "http://www.shutupmikeginn.com",
"display_url" : "shutupmikeginn.com",
"indices" : [
0,
23
]
}
]
},
"description" : {
"urls" : [
]
}
},
"protected" : false,
"followers_count" : 155598,
"friends_count" : 757,
"listed_count" : 1675,
"created_at" : "Wed Feb 02 18:21:51 +0000 2011",
"favourites_count" : 58329,
"utc_offset" : null,
"time_zone" : null,
"geo_enabled" : false,
"verified" : false,
"statuses_count" : 9001,
"lang" : "en",
"contributors_enabled" : false,
"is_translator" : false,
"is_translation_enabled" : false,
"profile_background_color" : "000000",
"profile_background_image_url" : "http://abs.twimg.com/images/themes/theme15/bg.png",
"profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme15/bg.png",
"profile_background_tile" : false,
"profile_image_url" : "http://pbs.twimg.com/profile_images/523668808020422656/szD5CZyb_normal.jpeg",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/523668808020422656/szD5CZyb_normal.jpeg",
"profile_banner_url" : "https://pbs.twimg.com/profile_banners/246394886/1460523073",
"profile_link_color" : "4A913C",
"profile_sidebar_border_color" : "000000",
"profile_sidebar_fill_color" : "000000",
"profile_text_color" : "000000",
"profile_use_background_image" : false,
"has_extended_profile" : true,
"default_profile" : false,
"default_profile_image" : false,
"following" : false,
"follow_request_sent" : false,
"notifications" : false
}
}
}
]
},
"source" : "<a href=\"http://twitter.com/download/iphone\" rel=\"nofollow\">Twitter for iPhone</a>",
"in_reply_to_status_id" : null,
"in_reply_to_status_id_str" : null,
"in_reply_to_user_id" : null,
"in_reply_to_user_id_str" : null,
"in_reply_to_screen_name" : null,
"user" : {
"id" : 21369740,
"id_str" : "21369740",
"name" : "Rob DenBleyker",
"screen_name" : "RobDenBleyker",
"location" : "Dallas",
"description" : "I'm not Rob Dyrdek. Don't follow me.",
"url" : "https://t.co/5jh1OQTAOO",
"entities" : {
"url" : {
"urls" : [
{
"url" : "https://t.co/5jh1OQTAOO",
"expanded_url" : "http://www.explosm.net",
"display_url" : "explosm.net",
"indices" : [
0,
23
]
}
]
},
"description" : {
"urls" : [
]
}
},
"protected" : false,
"followers_count" : 126457,
"friends_count" : 800,
"listed_count" : 1284,
"created_at" : "Fri Feb 20 03:26:24 +0000 2009",
"favourites_count" : 1452,
"utc_offset" : -18000,
"time_zone" : "Central Time (US & Canada)",
"geo_enabled" : true,
"verified" : false,
"statuses_count" : 8088,
"lang" : "en",
"contributors_enabled" : false,
"is_translator" : false,
"is_translation_enabled" : false,
"profile_background_color" : "49585E",
"profile_background_image_url" : "http://abs.twimg.com/images/themes/theme1/bg.png",
"profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme1/bg.png",
"profile_background_tile" : false,
"profile_image_url" : "http://pbs.twimg.com/profile_images/751256809873281024/-FuDkY2p_normal.jpg",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/751256809873281024/-FuDkY2p_normal.jpg",
"profile_link_color" : "0C90F5",
"profile_sidebar_border_color" : "C0DEED",
"profile_sidebar_fill_color" : "DDEEF6",
"profile_text_color" : "333333",
"profile_use_background_image" : false,
"has_extended_profile" : false,
"default_profile" : false,
"default_profile_image" : false,
"following" : true,
"follow_request_sent" : false,
"notifications" : false
},
"geo" : null,
"coordinates" : null,
"place" : null,
"contributors" : null,
"retweeted_status" : {
"created_at" : "Wed Aug 03 00:10:40 +0000 2016",
"id" : 760628917837312000,
"id_str" : "760628917837312000",
"text" : "Hey @ScottAdamsSays, @eedrk & I are big fans so we recut Dilbert to deal with contemporary social issues! Please RT! https://t.co/Dth5YBHXeu",
"truncated" : false,
"entities" : {
"hashtags" : [
],
"symbols" : [
],
"user_mentions" : [
{
"screen_name" : "ScottAdamsSays",
"name" : "Scott Adams",
"id" : 2853461537,
"id_str" : "2853461537",
"indices" : [
4,
19
]
},
{
"screen_name" : "eedrk",
"name" : "derek",
"id" : 1350600582,
"id_str" : "1350600582",
"indices" : [
21,
27
]
}
],
"urls" : [
],
"media" : [
{
"id" : 760627464456462336,
"id_str" : "760627464456462336",
"indices" : [
121,
144
],
"media_url" : "http://pbs.twimg.com/ext_tw_video_thumb/760627464456462336/pu/img/ZmNeZzX7qcwzsuon.jpg",
"media_url_https" : "https://pbs.twimg.com/ext_tw_video_thumb/760627464456462336/pu/img/ZmNeZzX7qcwzsuon.jpg",
"url" : "https://t.co/Dth5YBHXeu",
"display_url" : "pic.twitter.com/Dth5YBHXeu",
"expanded_url" : "http://twitter.com/shutupmikeginn/status/760628917837312000/video/1",
"type" : "photo",
"sizes" : {
"medium" : {
"w" : 600,
"h" : 411,
"resize" : "fit"
},
"thumb" : {
"w" : 150,
"h" : 150,
"resize" : "crop"
},
"large" : {
"w" : 700,
"h" : 480,
"resize" : "fit"
},
"small" : {
"w" : 340,
"h" : 233,
"resize" : "fit"
}
}
}
]
},
"extended_entities" : {
"media" : [
{
"id" : 760627464456462336,
"id_str" : "760627464456462336",
"indices" : [
121,
144
],
"media_url" : "http://pbs.twimg.com/ext_tw_video_thumb/760627464456462336/pu/img/ZmNeZzX7qcwzsuon.jpg",
"media_url_https" : "https://pbs.twimg.com/ext_tw_video_thumb/760627464456462336/pu/img/ZmNeZzX7qcwzsuon.jpg",
"url" : "https://t.co/Dth5YBHXeu",
"display_url" : "pic.twitter.com/Dth5YBHXeu",
"expanded_url" : "http://twitter.com/shutupmikeginn/status/760628917837312000/video/1",
"type" : "video",
"sizes" : {
"medium" : {
"w" : 600,
"h" : 411,
"resize" : "fit"
},
"thumb" : {
"w" : 150,
"h" : 150,
"resize" : "crop"
},
"large" : {
"w" : 700,
"h" : 480,
"resize" : "fit"
},
"small" : {
"w" : 340,
"h" : 233,
"resize" : "fit"
}
},
"video_info" : {
"aspect_ratio" : [
35,
24
],
"duration_millis" : 50017,
"variants" : [
{
"content_type" : "application/dash+xml",
"url" : "https://video.twimg.com/ext_tw_video/760627464456462336/pu/pl/WgyGZ2bR67CZKbIe.mpd"
},
{
"bitrate" : 320000,
"content_type" : "video/mp4",
"url" : "https://video.twimg.com/ext_tw_video/760627464456462336/pu/vid/262x180/bMwQb2LGoymiuNBF.mp4"
},
{
"content_type" : "application/x-mpegURL",
"url" : "https://video.twimg.com/ext_tw_video/760627464456462336/pu/pl/WgyGZ2bR67CZKbIe.m3u8"
},
{
"bitrate" : 832000,
"content_type" : "video/mp4",
"url" : "https://video.twimg.com/ext_tw_video/760627464456462336/pu/vid/524x360/akoT29AzRB-K7Tvf.mp4"
}
]
},
"additional_media_info" : {
"monetizable" : false
}
}
]
},
"source" : "<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter Web Client</a>",
"in_reply_to_status_id" : null,
"in_reply_to_status_id_str" : null,
"in_reply_to_user_id" : null,
"in_reply_to_user_id_str" : null,
"in_reply_to_screen_name" : null,
"user" : {
"id" : 246394886,
"id_str" : "246394886",
"name" : "shut up, mike",
"screen_name" : "shutupmikeginn",
"location" : "Los Angeles, CA",
"description" : "writer (left handed) // shutupmikeginn @ gmail . com // @midnight",
"url" : "https://t.co/JLpcO66Txj",
"entities" : {
"url" : {
"urls" : [
{
"url" : "https://t.co/JLpcO66Txj",
"expanded_url" : "http://www.shutupmikeginn.com",
"display_url" : "shutupmikeginn.com",
"indices" : [
0,
23
]
}
]
},
"description" : {
"urls" : [
]
}
},
"protected" : false,
"followers_count" : 155598,
"friends_count" : 757,
"listed_count" : 1675,
"created_at" : "Wed Feb 02 18:21:51 +0000 2011",
"favourites_count" : 58329,
"utc_offset" : null,
"time_zone" : null,
"geo_enabled" : false,
"verified" : false,
"statuses_count" : 9001,
"lang" : "en",
"contributors_enabled" : false,
"is_translator" : false,
"is_translation_enabled" : false,
"profile_background_color" : "000000",
"profile_background_image_url" : "http://abs.twimg.com/images/themes/theme15/bg.png",
"profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme15/bg.png",
"profile_background_tile" : false,
"profile_image_url" : "http://pbs.twimg.com/profile_images/523668808020422656/szD5CZyb_normal.jpeg",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/523668808020422656/szD5CZyb_normal.jpeg",
"profile_banner_url" : "https://pbs.twimg.com/profile_banners/246394886/1460523073",
"profile_link_color" : "4A913C",
"profile_sidebar_border_color" : "000000",
"profile_sidebar_fill_color" : "000000",
"profile_text_color" : "000000",
"profile_use_background_image" : false,
"has_extended_profile" : true,
"default_profile" : false,
"default_profile_image" : false,
"following" : false,
"follow_request_sent" : false,
"notifications" : false
},
"geo" : null,
"coordinates" : null,
"place" : null,
"contributors" : null,
"is_quote_status" : false,
"retweet_count" : 128,
"favorite_count" : 523,
"favorited" : false,
"retweeted" : false,
"possibly_sensitive" : false,
"possibly_sensitive_appealable" : false,
"lang" : "en"
},
"is_quote_status" : false,
"retweet_count" : 128,
"favorite_count" : 0,
"favorited" : false,
"retweeted" : false,
"possibly_sensitive" : false,
"possibly_sensitive_appealable" : false,
"lang" : "en"
}
""";
const string EMPTY_TWEET_WITH_MEDIA =
"""
{
"created_at" : "Wed Aug 03 02:48:12 +0000 2016",
"id" : 760668562323189761,
"id_str" : "760668562323189761",
"text" : "https://t.co/ffI4jeND7m",
"truncated" : false,
"entities" : {
"hashtags" : [
],
"symbols" : [
],
"user_mentions" : [
],
"urls" : [
],
"media" : [
{
"id" : 760668555239010304,
"id_str" : "760668555239010304",
"indices" : [
0,
23
],
"media_url" : "http://pbs.twimg.com/media/Co5wBVLUsAASfCW.jpg",
"media_url_https" : "https://pbs.twimg.com/media/Co5wBVLUsAASfCW.jpg",
"url" : "https://t.co/ffI4jeND7m",
"display_url" : "pic.twitter.com/ffI4jeND7m",
"expanded_url" : "http://twitter.com/RobDenBleyker/status/760668562323189761/photo/1",
"type" : "photo",
"sizes" : {
"large" : {
"w" : 820,
"h" : 300,
"resize" : "fit"
},
"small" : {
"w" : 680,
"h" : 249,
"resize" : "fit"
},
"medium" : {
"w" : 820,
"h" : 300,
"resize" : "fit"
},
"thumb" : {
"w" : 150,
"h" : 150,
"resize" : "crop"
}
}
}
]
},
"extended_entities" : {
"media" : [
{
"id" : 760668555239010304,
"id_str" : "760668555239010304",
"indices" : [
0,
23
],
"media_url" : "http://pbs.twimg.com/media/Co5wBVLUsAASfCW.jpg",
"media_url_https" : "https://pbs.twimg.com/media/Co5wBVLUsAASfCW.jpg",
"url" : "https://t.co/ffI4jeND7m",
"display_url" : "pic.twitter.com/ffI4jeND7m",
"expanded_url" : "http://twitter.com/RobDenBleyker/status/760668562323189761/photo/1",
"type" : "photo",
"sizes" : {
"large" : {
"w" : 820,
"h" : 300,
"resize" : "fit"
},
"small" : {
"w" : 680,
"h" : 249,
"resize" : "fit"
},
"medium" : {
"w" : 820,
"h" : 300,
"resize" : "fit"
},
"thumb" : {
"w" : 150,
"h" : 150,
"resize" : "crop"
}
}
}
]
},
"source" : "<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter Web Client</a>",
"in_reply_to_status_id" : null,
"in_reply_to_status_id_str" : null,
"in_reply_to_user_id" : null,
"in_reply_to_user_id_str" : null,
"in_reply_to_screen_name" : null,
"user" : {
"id" : 21369740,
"id_str" : "21369740",
"name" : "Rob DenBleyker",
"screen_name" : "RobDenBleyker",
"location" : "Dallas",
"description" : "I'm not Rob Dyrdek. Don't follow me.",
"url" : "https://t.co/5jh1OQTAOO",
"entities" : {
"url" : {
"urls" : [
{
"url" : "https://t.co/5jh1OQTAOO",
"expanded_url" : "http://www.explosm.net",
"display_url" : "explosm.net",
"indices" : [
0,
23
]
}
]
},
"description" : {
"urls" : [
]
}
},
"protected" : false,
"followers_count" : 126457,
"friends_count" : 800,
"listed_count" : 1284,
"created_at" : "Fri Feb 20 03:26:24 +0000 2009",
"favourites_count" : 1452,
"utc_offset" : -18000,
"time_zone" : "Central Time (US & Canada)",
"geo_enabled" : true,
"verified" : false,
"statuses_count" : 8088,
"lang" : "en",
"contributors_enabled" : false,
"is_translator" : false,
"is_translation_enabled" : false,
"profile_background_color" : "49585E",
"profile_background_image_url" : "http://abs.twimg.com/images/themes/theme1/bg.png",
"profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme1/bg.png",
"profile_background_tile" : false,
"profile_image_url" : "http://pbs.twimg.com/profile_images/751256809873281024/-FuDkY2p_normal.jpg",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/751256809873281024/-FuDkY2p_normal.jpg",
"profile_link_color" : "0C90F5",
"profile_sidebar_border_color" : "C0DEED",
"profile_sidebar_fill_color" : "DDEEF6",
"profile_text_color" : "333333",
"profile_use_background_image" : false,
"has_extended_profile" : false,
"default_profile" : false,
"default_profile_image" : false,
"following" : true,
"follow_request_sent" : false,
"notifications" : false
},
"geo" : null,
"coordinates" : null,
"place" : null,
"contributors" : null,
"is_quote_status" : false,
"retweet_count" : 90,
"favorite_count" : 238,
"favorited" : false,
"retweeted" : false,
"possibly_sensitive" : false,
"possibly_sensitive_appealable" : false,
"lang" : "und"
}
""";
const string EMPTY_RETWEET_WITH_MEDIA =
"""
{
"created_at" : "Wed Aug 03 01:22:42 +0000 2016",
"id" : 760647046835544064,
"id_str" : "760647046835544064",
"text" : "RT @shutupmikeginn: Hey @ScottAdamsSays, @eedrk & I are big fans so we recut Dilbert to deal with contemporary social issues! Please RT! ht…",
"truncated" : false,
"entities" : {
"hashtags" : [
],
"symbols" : [
],
"user_mentions" : [
{
"screen_name" : "shutupmikeginn",
"name" : "shut up, mike",
"id" : 246394886,
"id_str" : "246394886",
"indices" : [
3,
18
]
},
{
"screen_name" : "ScottAdamsSays",
"name" : "Scott Adams",
"id" : 2853461537,
"id_str" : "2853461537",
"indices" : [
24,
39
]
},
{
"screen_name" : "eedrk",
"name" : "derek",
"id" : 1350600582,
"id_str" : "1350600582",
"indices" : [
41,
47
]
}
],
"urls" : [
],
"media" : [
{
"id" : 760627464456462336,
"id_str" : "760627464456462336",
"indices" : [
143,
144
],
"media_url" : "http://pbs.twimg.com/ext_tw_video_thumb/760627464456462336/pu/img/ZmNeZzX7qcwzsuon.jpg",
"media_url_https" : "https://pbs.twimg.com/ext_tw_video_thumb/760627464456462336/pu/img/ZmNeZzX7qcwzsuon.jpg",
"url" : "https://t.co/Dth5YBHXeu",
"display_url" : "pic.twitter.com/Dth5YBHXeu",
"expanded_url" : "http://twitter.com/shutupmikeginn/status/760628917837312000/video/1",
"type" : "photo",
"sizes" : {
"medium" : {
"w" : 600,
"h" : 411,
"resize" : "fit"
},
"thumb" : {
"w" : 150,
"h" : 150,
"resize" : "crop"
},
"large" : {
"w" : 700,
"h" : 480,
"resize" : "fit"
},
"small" : {
"w" : 340,
"h" : 233,
"resize" : "fit"
}
},
"source_status_id" : 760628917837312000,
"source_status_id_str" : "760628917837312000",
"source_user_id" : 246394886,
"source_user_id_str" : "246394886"
}
]
},
"extended_entities" : {
"media" : [
{
"id" : 760627464456462336,
"id_str" : "760627464456462336",
"indices" : [
143,
144
],
"media_url" : "http://pbs.twimg.com/ext_tw_video_thumb/760627464456462336/pu/img/ZmNeZzX7qcwzsuon.jpg",
"media_url_https" : "https://pbs.twimg.com/ext_tw_video_thumb/760627464456462336/pu/img/ZmNeZzX7qcwzsuon.jpg",
"url" : "https://t.co/Dth5YBHXeu",
"display_url" : "pic.twitter.com/Dth5YBHXeu",
"expanded_url" : "http://twitter.com/shutupmikeginn/status/760628917837312000/video/1",
"type" : "video",
"sizes" : {
"medium" : {
"w" : 600,
"h" : 411,
"resize" : "fit"
},
"thumb" : {
"w" : 150,
"h" : 150,
"resize" : "crop"
},
"large" : {
"w" : 700,
"h" : 480,
"resize" : "fit"
},
"small" : {
"w" : 340,
"h" : 233,
"resize" : "fit"
}
},
"source_status_id" : 760628917837312000,
"source_status_id_str" : "760628917837312000",
"source_user_id" : 246394886,
"source_user_id_str" : "246394886",
"video_info" : {
"aspect_ratio" : [
35,
24
],
"duration_millis" : 50017,
"variants" : [
{
"content_type" : "application/dash+xml",
"url" : "https://video.twimg.com/ext_tw_video/760627464456462336/pu/pl/WgyGZ2bR67CZKbIe.mpd"
},
{
"bitrate" : 320000,
"content_type" : "video/mp4",
"url" : "https://video.twimg.com/ext_tw_video/760627464456462336/pu/vid/262x180/bMwQb2LGoymiuNBF.mp4"
},
{
"content_type" : "application/x-mpegURL",
"url" : "https://video.twimg.com/ext_tw_video/760627464456462336/pu/pl/WgyGZ2bR67CZKbIe.m3u8"
},
{
"bitrate" : 832000,
"content_type" : "video/mp4",
"url" : "https://video.twimg.com/ext_tw_video/760627464456462336/pu/vid/524x360/akoT29AzRB-K7Tvf.mp4"
}
]
},
"additional_media_info" : {
"monetizable" : false,
"source_user" : {
"id" : 246394886,
"id_str" : "246394886",
"name" : "shut up, mike",
"screen_name" : "shutupmikeginn",
"location" : "Los Angeles, CA",
"description" : "writer (left handed) // shutupmikeginn @ gmail . com // @midnight",
"url" : "https://t.co/JLpcO66Txj",
"entities" : {
"url" : {
"urls" : [
{
"url" : "https://t.co/JLpcO66Txj",
"expanded_url" : "http://www.shutupmikeginn.com",
"display_url" : "shutupmikeginn.com",
"indices" : [
0,
23
]
}
]
},
"description" : {
"urls" : [
]
}
},
"protected" : false,
"followers_count" : 155598,
"friends_count" : 757,
"listed_count" : 1675,
"created_at" : "Wed Feb 02 18:21:51 +0000 2011",
"favourites_count" : 58329,
"utc_offset" : null,
"time_zone" : null,
"geo_enabled" : false,
"verified" : false,
"statuses_count" : 9001,
"lang" : "en",
"contributors_enabled" : false,
"is_translator" : false,
"is_translation_enabled" : false,
"profile_background_color" : "000000",
"profile_background_image_url" : "http://abs.twimg.com/images/themes/theme15/bg.png",
"profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme15/bg.png",
"profile_background_tile" : false,
"profile_image_url" : "http://pbs.twimg.com/profile_images/523668808020422656/szD5CZyb_normal.jpeg",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/523668808020422656/szD5CZyb_normal.jpeg",
"profile_banner_url" : "https://pbs.twimg.com/profile_banners/246394886/1460523073",
"profile_link_color" : "4A913C",
"profile_sidebar_border_color" : "000000",
"profile_sidebar_fill_color" : "000000",
"profile_text_color" : "000000",
"profile_use_background_image" : false,
"has_extended_profile" : true,
"default_profile" : false,
"default_profile_image" : false,
"following" : false,
"follow_request_sent" : false,
"notifications" : false
}
}
}
]
},
"source" : "<a href=\"http://twitter.com/download/iphone\" rel=\"nofollow\">Twitter for iPhone</a>",
"in_reply_to_status_id" : null,
"in_reply_to_status_id_str" : null,
"in_reply_to_user_id" : null,
"in_reply_to_user_id_str" : null,
"in_reply_to_screen_name" : null,
"user" : {
"id" : 21369740,
"id_str" : "21369740",
"name" : "Rob DenBleyker",
"screen_name" : "RobDenBleyker",
"location" : "Dallas",
"description" : "I'm not Rob Dyrdek. Don't follow me.",
"url" : "https://t.co/5jh1OQTAOO",
"entities" : {
"url" : {
"urls" : [
{
"url" : "https://t.co/5jh1OQTAOO",
"expanded_url" : "http://www.explosm.net",
"display_url" : "explosm.net",
"indices" : [
0,
23
]
}
]
},
"description" : {
"urls" : [
]
}
},
"protected" : false,
"followers_count" : 126457,
"friends_count" : 800,
"listed_count" : 1284,
"created_at" : "Fri Feb 20 03:26:24 +0000 2009",
"favourites_count" : 1452,
"utc_offset" : -18000,
"time_zone" : "Central Time (US & Canada)",
"geo_enabled" : true,
"verified" : false,
"statuses_count" : 8088,
"lang" : "en",
"contributors_enabled" : false,
"is_translator" : false,
"is_translation_enabled" : false,
"profile_background_color" : "49585E",
"profile_background_image_url" : "http://abs.twimg.com/images/themes/theme1/bg.png",
"profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme1/bg.png",
"profile_background_tile" : false,
"profile_image_url" : "http://pbs.twimg.com/profile_images/751256809873281024/-FuDkY2p_normal.jpg",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/751256809873281024/-FuDkY2p_normal.jpg",
"profile_link_color" : "0C90F5",
"profile_sidebar_border_color" : "C0DEED",
"profile_sidebar_fill_color" : "DDEEF6",
"profile_text_color" : "333333",
"profile_use_background_image" : false,
"has_extended_profile" : false,
"default_profile" : false,
"default_profile_image" : false,
"following" : true,
"follow_request_sent" : false,
"notifications" : false
},
"geo" : null,
"coordinates" : null,
"place" : null,
"contributors" : null,
"retweeted_status" : {
"created_at" : "Wed Aug 03 00:10:40 +0000 2016",
"id" : 760628917837312000,
"id_str" : "760628917837312000",
"text" : "",
"truncated" : false,
"entities" : {
"hashtags" : [
],
"symbols" : [
],
"user_mentions" : [
{
"screen_name" : "ScottAdamsSays",
"name" : "Scott Adams",
"id" : 2853461537,
"id_str" : "2853461537",
"indices" : [
4,
19
]
},
{
"screen_name" : "eedrk",
"name" : "derek",
"id" : 1350600582,
"id_str" : "1350600582",
"indices" : [
21,
27
]
}
],
"urls" : [
],
"media" : [
{
"id" : 760627464456462336,
"id_str" : "760627464456462336",
"indices" : [
121,
144
],
"media_url" : "http://pbs.twimg.com/ext_tw_video_thumb/760627464456462336/pu/img/ZmNeZzX7qcwzsuon.jpg",
"media_url_https" : "https://pbs.twimg.com/ext_tw_video_thumb/760627464456462336/pu/img/ZmNeZzX7qcwzsuon.jpg",
"url" : "https://t.co/Dth5YBHXeu",
"display_url" : "pic.twitter.com/Dth5YBHXeu",
"expanded_url" : "http://twitter.com/shutupmikeginn/status/760628917837312000/video/1",
"type" : "photo",
"sizes" : {
"medium" : {
"w" : 600,
"h" : 411,
"resize" : "fit"
},
"thumb" : {
"w" : 150,
"h" : 150,
"resize" : "crop"
},
"large" : {
"w" : 700,
"h" : 480,
"resize" : "fit"
},
"small" : {
"w" : 340,
"h" : 233,
"resize" : "fit"
}
}
}
]
},
"extended_entities" : {
"media" : [
{
"id" : 760627464456462336,
"id_str" : "760627464456462336",
"indices" : [
121,
144
],
"media_url" : "http://pbs.twimg.com/ext_tw_video_thumb/760627464456462336/pu/img/ZmNeZzX7qcwzsuon.jpg",
"media_url_https" : "https://pbs.twimg.com/ext_tw_video_thumb/760627464456462336/pu/img/ZmNeZzX7qcwzsuon.jpg",
"url" : "https://t.co/Dth5YBHXeu",
"display_url" : "pic.twitter.com/Dth5YBHXeu",
"expanded_url" : "http://twitter.com/shutupmikeginn/status/760628917837312000/video/1",
"type" : "video",
"sizes" : {
"medium" : {
"w" : 600,
"h" : 411,
"resize" : "fit"
},
"thumb" : {
"w" : 150,
"h" : 150,
"resize" : "crop"
},
"large" : {
"w" : 700,
"h" : 480,
"resize" : "fit"
},
"small" : {
"w" : 340,
"h" : 233,
"resize" : "fit"
}
},
"video_info" : {
"aspect_ratio" : [
35,
24
],
"duration_millis" : 50017,
"variants" : [
{
"content_type" : "application/dash+xml",
"url" : "https://video.twimg.com/ext_tw_video/760627464456462336/pu/pl/WgyGZ2bR67CZKbIe.mpd"
},
{
"bitrate" : 320000,
"content_type" : "video/mp4",
"url" : "https://video.twimg.com/ext_tw_video/760627464456462336/pu/vid/262x180/bMwQb2LGoymiuNBF.mp4"
},
{
"content_type" : "application/x-mpegURL",
"url" : "https://video.twimg.com/ext_tw_video/760627464456462336/pu/pl/WgyGZ2bR67CZKbIe.m3u8"
},
{
"bitrate" : 832000,
"content_type" : "video/mp4",
"url" : "https://video.twimg.com/ext_tw_video/760627464456462336/pu/vid/524x360/akoT29AzRB-K7Tvf.mp4"
}
]
},
"additional_media_info" : {
"monetizable" : false
}
}
]
},
"source" : "<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter Web Client</a>",
"in_reply_to_status_id" : null,
"in_reply_to_status_id_str" : null,
"in_reply_to_user_id" : null,
"in_reply_to_user_id_str" : null,
"in_reply_to_screen_name" : null,
"user" : {
"id" : 246394886,
"id_str" : "246394886",
"name" : "shut up, mike",
"screen_name" : "shutupmikeginn",
"location" : "Los Angeles, CA",
"description" : "writer (left handed) // shutupmikeginn @ gmail . com // @midnight",
"url" : "https://t.co/JLpcO66Txj",
"entities" : {
"url" : {
"urls" : [
{
"url" : "https://t.co/JLpcO66Txj",
"expanded_url" : "http://www.shutupmikeginn.com",
"display_url" : "shutupmikeginn.com",
"indices" : [
0,
23
]
}
]
},
"description" : {
"urls" : [
]
}
},
"protected" : false,
"followers_count" : 155598,
"friends_count" : 757,
"listed_count" : 1675,
"created_at" : "Wed Feb 02 18:21:51 +0000 2011",
"favourites_count" : 58329,
"utc_offset" : null,
"time_zone" : null,
"geo_enabled" : false,
"verified" : false,
"statuses_count" : 9001,
"lang" : "en",
"contributors_enabled" : false,
"is_translator" : false,
"is_translation_enabled" : false,
"profile_background_color" : "000000",
"profile_background_image_url" : "http://abs.twimg.com/images/themes/theme15/bg.png",
"profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme15/bg.png",
"profile_background_tile" : false,
"profile_image_url" : "http://pbs.twimg.com/profile_images/523668808020422656/szD5CZyb_normal.jpeg",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/523668808020422656/szD5CZyb_normal.jpeg",
"profile_banner_url" : "https://pbs.twimg.com/profile_banners/246394886/1460523073",
"profile_link_color" : "4A913C",
"profile_sidebar_border_color" : "000000",
"profile_sidebar_fill_color" : "000000",
"profile_text_color" : "000000",
"profile_use_background_image" : false,
"has_extended_profile" : true,
"default_profile" : false,
"default_profile_image" : false,
"following" : false,
"follow_request_sent" : false,
"notifications" : false
},
"geo" : null,
"coordinates" : null,
"place" : null,
"contributors" : null,
"is_quote_status" : false,
"retweet_count" : 128,
"favorite_count" : 523,
"favorited" : false,
"retweeted" : false,
"possibly_sensitive" : false,
"possibly_sensitive_appealable" : false,
"lang" : "en"
},
"is_quote_status" : false,
"retweet_count" : 128,
"favorite_count" : 0,
"favorited" : false,
"retweeted" : false,
"possibly_sensitive" : false,
"possibly_sensitive_appealable" : false,
"lang" : "en"
}
""";
const string VIDEO_AND_THUMBNAIL =
"""
{
"created_at" : "Sat Nov 05 19:41:06 +0000 2016",
"id" : 794987926157410308,
"id_str" : "794987926157410308",
"full_text" : "RT @mileysdrive: Truly iconic https://t.co/8gdSKk0Zx2",
"truncated" : false,
"display_text_range" : [
0,
53
],
"entities" : {
"hashtags" : [
],
"symbols" : [
],
"user_mentions" : [
{
"screen_name" : "mileysdrive",
"name" : "NSA agent jim",
"id" : 2624180621,
"id_str" : "2624180621",
"indices" : [
3,
15
]
}
],
"urls" : [
],
"media" : [
{
"id" : 793976804549754880,
"id_str" : "793976804549754880",
"indices" : [
30,
53
],
"media_url" : "http://pbs.twimg.com/media/CwTHbn3XgAEcDEr.jpg",
"media_url_https" : "https://pbs.twimg.com/media/CwTHbn3XgAEcDEr.jpg",
"url" : "https://t.co/8gdSKk0Zx2",
"display_url" : "pic.twitter.com/8gdSKk0Zx2",
"expanded_url" : "https://twitter.com/LateNightSeth/status/793982502008397825/video/1",
"type" : "photo",
"sizes" : {
"large" : {
"w" : 1273,
"h" : 715,
"resize" : "fit"
},
"thumb" : {
"w" : 150,
"h" : 150,
"resize" : "crop"
},
"small" : {
"w" : 680,
"h" : 382,
"resize" : "fit"
},
"medium" : {
"w" : 1200,
"h" : 674,
"resize" : "fit"
}
},
"source_status_id" : 793982502008397825,
"source_status_id_str" : "793982502008397825",
"source_user_id" : 570290656,
"source_user_id_str" : "570290656"
}
]
},
"extended_entities" : {
"media" : [
{
"id" : 793976804549754880,
"id_str" : "793976804549754880",
"indices" : [
30,
53
],
"media_url" : "http://pbs.twimg.com/media/CwTHbn3XgAEcDEr.jpg",
"media_url_https" : "https://pbs.twimg.com/media/CwTHbn3XgAEcDEr.jpg",
"url" : "https://t.co/8gdSKk0Zx2",
"display_url" : "pic.twitter.com/8gdSKk0Zx2",
"expanded_url" : "https://twitter.com/LateNightSeth/status/793982502008397825/video/1",
"type" : "video",
"sizes" : {
"large" : {
"w" : 1273,
"h" : 715,
"resize" : "fit"
},
"thumb" : {
"w" : 150,
"h" : 150,
"resize" : "crop"
},
"small" : {
"w" : 680,
"h" : 382,
"resize" : "fit"
},
"medium" : {
"w" : 1200,
"h" : 674,
"resize" : "fit"
}
},
"source_status_id" : 793982502008397825,
"source_status_id_str" : "793982502008397825",
"source_user_id" : 570290656,
"source_user_id_str" : "570290656",
"video_info" : {
"aspect_ratio" : [
16,
9
],
"duration_millis" : 72440,
"variants" : [
{
"bitrate" : 320000,
"content_type" : "video/mp4",
"url" : "https://video.twimg.com/amplify_video/793976804549754880/vid/320x180/wO9JSutxwKtnr-4M.mp4"
},
{
"bitrate" : 2176000,
"content_type" : "video/mp4",
"url" : "https://video.twimg.com/amplify_video/793976804549754880/vid/1280x720/zMwtzVr0k_5SYkOG.mp4"
},
{
"content_type" : "application/x-mpegURL",
"url" : "https://video.twimg.com/amplify_video/793976804549754880/pl/Vj9EDa2m-8tTq332.m3u8"
},
{
"bitrate" : 832000,
"content_type" : "video/mp4",
"url" : "https://video.twimg.com/amplify_video/793976804549754880/vid/640x360/1WAEEC98fuAilBVX.mp4"
},
{
"content_type" : "application/dash+xml",
"url" : "https://video.twimg.com/amplify_video/793976804549754880/pl/Vj9EDa2m-8tTq332.mpd"
}
]
},
"additional_media_info" : {
"title" : "",
"description" : "",
"call_to_actions" : {
"visit_site" : {
"url" : "https://www.youtube.com/user/LateNightSeth/featured"
}
},
"embeddable" : true,
"monetizable" : false,
"source_user" : {
"id" : 570290656,
"id_str" : "570290656",
"name" : "Late Night",
"screen_name" : "LateNightSeth",
"location" : "Studio 8G - Rockefeller Center",
"description" : "Official Twitter handle for Late Night with @SethMeyers, airing weeknights at 12:35/11:35c on @NBC. #LNSM",
"url" : "http://t.co/af2p12D0GI",
"entities" : {
"url" : {
"urls" : [
{
"url" : "http://t.co/af2p12D0GI",
"expanded_url" : "http://latenightseth.com",
"display_url" : "latenightseth.com",
"indices" : [
0,
22
]
}
]
},
"description" : {
"urls" : [
]
}
},
"protected" : false,
"followers_count" : 291188,
"friends_count" : 1743,
"listed_count" : 1467,
"created_at" : "Thu May 03 21:08:00 +0000 2012",
"favourites_count" : 2440,
"utc_offset" : -18000,
"time_zone" : "Eastern Time (US & Canada)",
"geo_enabled" : true,
"verified" : true,
"statuses_count" : 8635,
"lang" : "en",
"contributors_enabled" : false,
"is_translator" : false,
"is_translation_enabled" : false,
"profile_background_color" : "C0DEED",
"profile_background_image_url" : "http://pbs.twimg.com/profile_background_images/438333165292097536/Z0HtuqUc.jpeg",
"profile_background_image_url_https" : "https://pbs.twimg.com/profile_background_images/438333165292097536/Z0HtuqUc.jpeg",
"profile_background_tile" : false,
"profile_image_url" : "http://pbs.twimg.com/profile_images/781548560944865280/9dpThu5h_normal.jpg",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/781548560944865280/9dpThu5h_normal.jpg",
"profile_banner_url" : "https://pbs.twimg.com/profile_banners/570290656/1476483213",
"profile_link_color" : "0084B4",
"profile_sidebar_border_color" : "FFFFFF",
"profile_sidebar_fill_color" : "DDEEF6",
"profile_text_color" : "333333",
"profile_use_background_image" : true,
"has_extended_profile" : false,
"default_profile" : false,
"default_profile_image" : false,
"following" : false,
"follow_request_sent" : false,
"notifications" : false,
"translator_type" : "none"
}
}
}
]
},
"source" : "<a href=\"http://twitter.com/download/iphone\" rel=\"nofollow\">Twitter for iPhone</a>",
"in_reply_to_status_id" : null,
"in_reply_to_status_id_str" : null,
"in_reply_to_user_id" : null,
"in_reply_to_user_id_str" : null,
"in_reply_to_screen_name" : null,
"user" : {
"id" : 21369740,
"id_str" : "21369740",
"name" : "Rob DenBleyker",
"screen_name" : "RobDenBleyker",
"location" : "Dallas",
"description" : "I'm not Rob Dyrdek. Don't follow me.",
"url" : "https://t.co/5jh1OQTAOO",
"entities" : {
"url" : {
"urls" : [
{
"url" : "https://t.co/5jh1OQTAOO",
"expanded_url" : "http://www.explosm.net",
"display_url" : "explosm.net",
"indices" : [
0,
23
]
}
]
},
"description" : {
"urls" : [
]
}
},
"protected" : false,
"followers_count" : 126727,
"friends_count" : 815,
"listed_count" : 1287,
"created_at" : "Fri Feb 20 03:26:24 +0000 2009",
"favourites_count" : 1543,
"utc_offset" : -18000,
"time_zone" : "Central Time (US & Canada)",
"geo_enabled" : true,
"verified" : false,
"statuses_count" : 8276,
"lang" : "en",
"contributors_enabled" : false,
"is_translator" : false,
"is_translation_enabled" : false,
"profile_background_color" : "49585E",
"profile_background_image_url" : "http://abs.twimg.com/images/themes/theme1/bg.png",
"profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme1/bg.png",
"profile_background_tile" : false,
"profile_image_url" : "http://pbs.twimg.com/profile_images/769014291756441601/b0axYzlg_normal.jpg",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/769014291756441601/b0axYzlg_normal.jpg",
"profile_link_color" : "0C90F5",
"profile_sidebar_border_color" : "C0DEED",
"profile_sidebar_fill_color" : "DDEEF6",
"profile_text_color" : "333333",
"profile_use_background_image" : false,
"has_extended_profile" : false,
"default_profile" : false,
"default_profile_image" : false,
"following" : true,
"follow_request_sent" : false,
"notifications" : false,
"translator_type" : "none"
},
"geo" : null,
"coordinates" : null,
"place" : null,
"contributors" : null,
"retweeted_status" : {
"created_at" : "Thu Nov 03 19:59:57 +0000 2016",
"id" : 794267893257170944,
"id_str" : "794267893257170944",
"full_text" : "Truly iconic https://t.co/8gdSKk0Zx2",
"truncated" : false,
"display_text_range" : [
0,
36
],
"entities" : {
"hashtags" : [
],
"symbols" : [
],
"user_mentions" : [
],
"urls" : [
],
"media" : [
{
"id" : 793976804549754880,
"id_str" : "793976804549754880",
"indices" : [
13,
36
],
"media_url" : "http://pbs.twimg.com/media/CwTHbn3XgAEcDEr.jpg",
"media_url_https" : "https://pbs.twimg.com/media/CwTHbn3XgAEcDEr.jpg",
"url" : "https://t.co/8gdSKk0Zx2",
"display_url" : "pic.twitter.com/8gdSKk0Zx2",
"expanded_url" : "https://twitter.com/LateNightSeth/status/793982502008397825/video/1",
"type" : "photo",
"sizes" : {
"large" : {
"w" : 1273,
"h" : 715,
"resize" : "fit"
},
"thumb" : {
"w" : 150,
"h" : 150,
"resize" : "crop"
},
"small" : {
"w" : 680,
"h" : 382,
"resize" : "fit"
},
"medium" : {
"w" : 1200,
"h" : 674,
"resize" : "fit"
}
},
"source_status_id" : 793982502008397825,
"source_status_id_str" : "793982502008397825",
"source_user_id" : 570290656,
"source_user_id_str" : "570290656"
}
]
},
"extended_entities" : {
"media" : [
{
"id" : 793976804549754880,
"id_str" : "793976804549754880",
"indices" : [
13,
36
],
"media_url" : "http://pbs.twimg.com/media/CwTHbn3XgAEcDEr.jpg",
"media_url_https" : "https://pbs.twimg.com/media/CwTHbn3XgAEcDEr.jpg",
"url" : "https://t.co/8gdSKk0Zx2",
"display_url" : "pic.twitter.com/8gdSKk0Zx2",
"expanded_url" : "https://twitter.com/LateNightSeth/status/793982502008397825/video/1",
"type" : "video",
"sizes" : {
"large" : {
"w" : 1273,
"h" : 715,
"resize" : "fit"
},
"thumb" : {
"w" : 150,
"h" : 150,
"resize" : "crop"
},
"small" : {
"w" : 680,
"h" : 382,
"resize" : "fit"
},
"medium" : {
"w" : 1200,
"h" : 674,
"resize" : "fit"
}
},
"source_status_id" : 793982502008397825,
"source_status_id_str" : "793982502008397825",
"source_user_id" : 570290656,
"source_user_id_str" : "570290656",
"video_info" : {
"aspect_ratio" : [
16,
9
],
"duration_millis" : 72440,
"variants" : [
{
"bitrate" : 320000,
"content_type" : "video/mp4",
"url" : "https://video.twimg.com/amplify_video/793976804549754880/vid/320x180/wO9JSutxwKtnr-4M.mp4"
},
{
"bitrate" : 2176000,
"content_type" : "video/mp4",
"url" : "https://video.twimg.com/amplify_video/793976804549754880/vid/1280x720/zMwtzVr0k_5SYkOG.mp4"
},
{
"content_type" : "application/x-mpegURL",
"url" : "https://video.twimg.com/amplify_video/793976804549754880/pl/Vj9EDa2m-8tTq332.m3u8"
},
{
"bitrate" : 832000,
"content_type" : "video/mp4",
"url" : "https://video.twimg.com/amplify_video/793976804549754880/vid/640x360/1WAEEC98fuAilBVX.mp4"
},
{
"content_type" : "application/dash+xml",
"url" : "https://video.twimg.com/amplify_video/793976804549754880/pl/Vj9EDa2m-8tTq332.mpd"
}
]
},
"additional_media_info" : {
"title" : "",
"description" : "",
"call_to_actions" : {
"visit_site" : {
"url" : "https://www.youtube.com/user/LateNightSeth/featured"
}
},
"embeddable" : true,
"monetizable" : false,
"source_user" : {
"id" : 570290656,
"id_str" : "570290656",
"name" : "Late Night",
"screen_name" : "LateNightSeth",
"location" : "Studio 8G - Rockefeller Center",
"description" : "Official Twitter handle for Late Night with @SethMeyers, airing weeknights at 12:35/11:35c on @NBC. #LNSM",
"url" : "http://t.co/af2p12D0GI",
"entities" : {
"url" : {
"urls" : [
{
"url" : "http://t.co/af2p12D0GI",
"expanded_url" : "http://latenightseth.com",
"display_url" : "latenightseth.com",
"indices" : [
0,
22
]
}
]
},
"description" : {
"urls" : [
]
}
},
"protected" : false,
"followers_count" : 291188,
"friends_count" : 1743,
"listed_count" : 1467,
"created_at" : "Thu May 03 21:08:00 +0000 2012",
"favourites_count" : 2440,
"utc_offset" : -18000,
"time_zone" : "Eastern Time (US & Canada)",
"geo_enabled" : true,
"verified" : true,
"statuses_count" : 8635,
"lang" : "en",
"contributors_enabled" : false,
"is_translator" : false,
"is_translation_enabled" : false,
"profile_background_color" : "C0DEED",
"profile_background_image_url" : "http://pbs.twimg.com/profile_background_images/438333165292097536/Z0HtuqUc.jpeg",
"profile_background_image_url_https" : "https://pbs.twimg.com/profile_background_images/438333165292097536/Z0HtuqUc.jpeg",
"profile_background_tile" : false,
"profile_image_url" : "http://pbs.twimg.com/profile_images/781548560944865280/9dpThu5h_normal.jpg",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/781548560944865280/9dpThu5h_normal.jpg",
"profile_banner_url" : "https://pbs.twimg.com/profile_banners/570290656/1476483213",
"profile_link_color" : "0084B4",
"profile_sidebar_border_color" : "FFFFFF",
"profile_sidebar_fill_color" : "DDEEF6",
"profile_text_color" : "333333",
"profile_use_background_image" : true,
"has_extended_profile" : false,
"default_profile" : false,
"default_profile_image" : false,
"following" : false,
"follow_request_sent" : false,
"notifications" : false,
"translator_type" : "none"
}
}
}
]
},
"source" : "<a href=\"http://twitter.com/download/iphone\" rel=\"nofollow\">Twitter for iPhone</a>",
"in_reply_to_status_id" : null,
"in_reply_to_status_id_str" : null,
"in_reply_to_user_id" : null,
"in_reply_to_user_id_str" : null,
"in_reply_to_screen_name" : null,
"user" : {
"id" : 2624180621,
"id_str" : "2624180621",
"name" : "NSA agent jim",
"screen_name" : "mileysdrive",
"location" : "",
"description" : "cristina yang",
"url" : null,
"entities" : {
"description" : {
"urls" : [
]
}
},
"protected" : false,
"followers_count" : 16939,
"friends_count" : 124,
"listed_count" : 48,
"created_at" : "Thu Jun 19 23:54:07 +0000 2014",
"favourites_count" : 7577,
"utc_offset" : 7200,
"time_zone" : "Bucharest",
"geo_enabled" : true,
"verified" : false,
"statuses_count" : 5639,
"lang" : "en",
"contributors_enabled" : false,
"is_translator" : false,
"is_translation_enabled" : false,
"profile_background_color" : "C0DEED",
"profile_background_image_url" : "http://abs.twimg.com/images/themes/theme1/bg.png",
"profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme1/bg.png",
"profile_background_tile" : false,
"profile_image_url" : "http://pbs.twimg.com/profile_images/794467416331927552/LcPQANP8_normal.jpg",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/794467416331927552/LcPQANP8_normal.jpg",
"profile_banner_url" : "https://pbs.twimg.com/profile_banners/2624180621/1467532442",
"profile_link_color" : "1DA1F2",
"profile_sidebar_border_color" : "C0DEED",
"profile_sidebar_fill_color" : "DDEEF6",
"profile_text_color" : "333333",
"profile_use_background_image" : true,
"has_extended_profile" : false,
"default_profile" : true,
"default_profile_image" : false,
"following" : false,
"follow_request_sent" : false,
"notifications" : false,
"translator_type" : "none"
},
"geo" : null,
"coordinates" : null,
"place" : null,
"contributors" : null,
"is_quote_status" : false,
"retweet_count" : 7523,
"favorite_count" : 8028,
"favorited" : false,
"retweeted" : false,
"possibly_sensitive" : false,
"possibly_sensitive_appealable" : false,
"lang" : "en"
},
"is_quote_status" : false,
"retweet_count" : 7523,
"favorite_count" : 0,
"favorited" : false,
"retweeted" : false,
"possibly_sensitive" : false,
"possibly_sensitive_appealable" : false,
"lang" : "en"
}
""";
const string REPLY = """
{
"created_at" : "Sat Jan 28 09:23:50 +0000 2017",
"id" : 825273167560208384,
"id_str" : "825273167560208384",
"full_text" : "@explodingwalrus \"definitely\" as in \"xdg-settings get default-url-scheme-handler https\" returns chrome's desktop file?",
"truncated" : false,
"display_text_range" : [
17,
118
],
"entities" : {
"hashtags" : [
],
"symbols" : [
],
"user_mentions" : [
{
"screen_name" : "explodingwalrus",
"name" : "Carl Draper",
"id" : 44823886,
"id_str" : "44823886",
"indices" : [
0,
16
]
}
],
"urls" : [
]
},
"source" : "<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter Web Client</a>",
"in_reply_to_status_id" : 825269440556081153,
"in_reply_to_status_id_str" : "825269440556081153",
"in_reply_to_user_id" : 44823886,
"in_reply_to_user_id_str" : "44823886",
"in_reply_to_screen_name" : "explodingwalrus",
"user" : {
"id" : 2877682863,
"id_str" : "2877682863",
"name" : "Cawbird",
"screen_name" : "cawbirdclient",
"location" : "",
"description" : "If there's no bug report for it, it doesn't exist.\n\nThis account is run by a highly-paid intern, not @baedert himself.\n\nStill not Cawbird. Or @Cawbird.",
"url" : "https://t.co/yGvX7Nf6i3",
"entities" : {
"url" : {
"urls" : [
{
"url" : "https://t.co/yGvX7Nf6i3",
"expanded_url" : "http://cawbird.baedert.org",
"display_url" : "cawbird.baedert.org",
"indices" : [
0,
23
]
}
]
},
"description" : {
"urls" : [
]
}
},
"protected" : false,
"followers_count" : 430,
"friends_count" : 3,
"listed_count" : 24,
"created_at" : "Sat Nov 15 08:08:32 +0000 2014",
"favourites_count" : 22,
"utc_offset" : 7200,
"time_zone" : "Ljubljana",
"geo_enabled" : false,
"verified" : false,
"statuses_count" : 376,
"lang" : "en",
"contributors_enabled" : false,
"is_translator" : false,
"is_translation_enabled" : false,
"profile_background_color" : "FAB81E",
"profile_background_image_url" : "http://abs.twimg.com/images/themes/theme1/bg.png",
"profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme1/bg.png",
"profile_background_tile" : false,
"profile_image_url" : "http://pbs.twimg.com/profile_images/533595923679432704/bIWqAMTk_normal.png",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/533595923679432704/bIWqAMTk_normal.png",
"profile_link_color" : "000000",
"profile_sidebar_border_color" : "000000",
"profile_sidebar_fill_color" : "000000",
"profile_text_color" : "000000",
"profile_use_background_image" : true,
"has_extended_profile" : false,
"default_profile" : false,
"default_profile_image" : false,
"following" : true,
"follow_request_sent" : false,
"notifications" : false,
"translator_type" : "none"
},
"geo" : null,
"coordinates" : null,
"place" : null,
"contributors" : null,
"is_quote_status" : false,
"retweet_count" : 0,
"favorite_count" : 0,
"favorited" : false,
"retweeted" : false,
"lang" : "en"
}
""";
const string REPLY_TO_TWO = """
{
"created_at" : "Mon Apr 17 13:01:46 +0000 2017",
"id" : 853956655020748801,
"id_str" : "853956655020748801",
"full_text" : "@kaidjohnson @gnome Not everyone feels as confident switching to Linux. UKUI gives them a comfort blanket of familiarity.",
"truncated" : false,
"display_text_range" : [
20,
121
],
"entities" : {
"hashtags" : [
],
"symbols" : [
],
"user_mentions" : [
{
"screen_name" : "kaidjohnson",
"name" : "Kai Johnson",
"id" : 34798045,
"id_str" : "34798045",
"indices" : [
0,
12
]
},
{
"screen_name" : "gnome",
"name" : "GNOME",
"id" : 12579252,
"id_str" : "12579252",
"indices" : [
13,
19
]
}
],
"urls" : [
]
},
"source" : "<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter Web Client</a>",
"in_reply_to_status_id" : 853956134323048452,
"in_reply_to_status_id_str" : "853956134323048452",
"in_reply_to_user_id" : 34798045,
"in_reply_to_user_id_str" : "34798045",
"in_reply_to_screen_name" : "kaidjohnson",
"user" : {
"id" : 72915446,
"id_str" : "72915446",
"name" : "OMG! UBUNTU!",
"screen_name" : "omgubuntu",
"location" : "US/UK",
"description" : "Your #1 source for the latest #Ubuntu Linux news, apps, tips, gaming & more. Got news? joey[at]ohso.io",
"url" : "https://t.co/E0SDJKEG9w",
"entities" : {
"url" : {
"urls" : [
{
"url" : "https://t.co/E0SDJKEG9w",
"expanded_url" : "http://www.omgubuntu.co.uk",
"display_url" : "omgubuntu.co.uk",
"indices" : [
0,
23
]
}
]
},
"description" : {
"urls" : [
]
}
},
"protected" : false,
"followers_count" : 94994,
"friends_count" : 54,
"listed_count" : 3816,
"created_at" : "Wed Sep 09 18:26:36 +0000 2009",
"favourites_count" : 2689,
"utc_offset" : 3600,
"time_zone" : "London",
"geo_enabled" : true,
"verified" : false,
"statuses_count" : 12699,
"lang" : "en",
"contributors_enabled" : false,
"is_translator" : false,
"is_translation_enabled" : false,
"profile_background_color" : "4D1F41",
"profile_background_image_url" : "http://pbs.twimg.com/profile_background_images/458275648939622400/g2-00Dua.png",
"profile_background_image_url_https" : "https://pbs.twimg.com/profile_background_images/458275648939622400/g2-00Dua.png",
"profile_background_tile" : false,
"profile_image_url" : "http://pbs.twimg.com/profile_images/627831364692389888/L3tujQ89_normal.png",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/627831364692389888/L3tujQ89_normal.png",
"profile_banner_url" : "https://pbs.twimg.com/profile_banners/72915446/1485460019",
"profile_link_color" : "009999",
"profile_sidebar_border_color" : "FFFFFF",
"profile_sidebar_fill_color" : "FFFFFF",
"profile_text_color" : "303030",
"profile_use_background_image" : true,
"has_extended_profile" : false,
"default_profile" : false,
"default_profile_image" : false,
"following" : true,
"follow_request_sent" : false,
"notifications" : false,
"translator_type" : "regular"
},
"geo" : null,
"coordinates" : null,
"place" : null,
"contributors" : null,
"is_quote_status" : false,
"retweet_count" : 0,
"favorite_count" : 1,
"favorited" : false,
"retweeted" : false,
"lang" : "en"
}
""";
const string REPLY2 = """
{
"created_at" : "Mon Apr 17 15:16:18 +0000 2017",
"id" : 853990508326252550,
"id_str" : "853990508326252550",
"full_text" : "@jjdesmond @_UBRAS_ @franalsworth @4Apes @katy4apes @theAliceRoberts @JaneGoodallUK @Jane_Goodall @JaneGoodallInst And here's the link for tickets again ... https://t.co/a9lOVMouNK",
"truncated" : false,
"display_text_range" : [
115,
180
],
"entities" : {
"hashtags" : [
],
"symbols" : [
],
"user_mentions" : [
{
"screen_name" : "jjdesmond",
"name" : "Jimmy Jenny Desmond",
"id" : 21278482,
"id_str" : "21278482",
"indices" : [
0,
10
]
},
{
"screen_name" : "_UBRAS_",
"name" : "Roots and Shoots UOB",
"id" : 803329927974096896,
"id_str" : "803329927974096896",
"indices" : [
11,
19
]
},
{
"screen_name" : "franalsworth",
"name" : "Fran",
"id" : 776983919287754752,
"id_str" : "776983919287754752",
"indices" : [
20,
33
]
},
{
"screen_name" : "4Apes",
"name" : "Ian Redmond",
"id" : 155889035,
"id_str" : "155889035",
"indices" : [
34,
40
]
},
{
"screen_name" : "katy4apes",
"name" : "Katy Jedamzik",
"id" : 159608654,
"id_str" : "159608654",
"indices" : [
41,
51
]
},
{
"screen_name" : "theAliceRoberts",
"name" : "Prof Alice Roberts",
"id" : 260211154,
"id_str" : "260211154",
"indices" : [
52,
68
]
},
{
"screen_name" : "JaneGoodallUK",
"name" : "Roots & Shoots UK",
"id" : 423423823,
"id_str" : "423423823",
"indices" : [
69,
83
]
},
{
"screen_name" : "Jane_Goodall",
"name" : "Jane Goodall",
"id" : 235157216,
"id_str" : "235157216",
"indices" : [
84,
97
]
},
{
"screen_name" : "JaneGoodallInst",
"name" : "JaneGoodallInstitute",
"id" : 39822897,
"id_str" : "39822897",
"indices" : [
98,
114
]
}
],
"urls" : [
{
"url" : "https://t.co/a9lOVMouNK",
"expanded_url" : "https://www.eventbrite.com/e/working-with-apes-tickets-33089771397",
"display_url" : "eventbrite.com/e/working-with…",
"indices" : [
157,
180
]
}
]
},
"source" : "<a href=\"http://twitter.com/download/iphone\" rel=\"nofollow\">Twitter for iPhone</a>",
"in_reply_to_status_id" : 853925036696141824,
"in_reply_to_status_id_str" : "853925036696141824",
"in_reply_to_user_id" : 21278482,
"in_reply_to_user_id_str" : "21278482",
"in_reply_to_screen_name" : "jjdesmond",
"user" : {
"id" : 415472140,
"id_str" : "415472140",
"name" : "Ben Garrod",
"screen_name" : "Ben_garrod",
"location" : "Bristol&Norfolk",
"description" : "Monkey-chaser, TV-talker, bone geek and Teaching Fellow at @AngliaRuskin https://t.co/FXbftdxxTJ",
"url" : "https://t.co/1B9SDHfWoF",
"entities" : {
"url" : {
"urls" : [
{
"url" : "https://t.co/1B9SDHfWoF",
"expanded_url" : "http://www.josarsby.com/ben-garrod",
"display_url" : "josarsby.com/ben-garrod",
"indices" : [
0,
23
]
}
]
},
"description" : {
"urls" : [
{
"url" : "https://t.co/FXbftdxxTJ",
"expanded_url" : "http://www.anglia.ac.uk/science-and-technology/about/life-sciences/our-staff/ben-garrod",
"d
gitextract_nws3r4s9/
├── ._vimrc
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ └── feature_request.md
│ └── workflows/
│ └── main.yml
├── .gitignore
├── .tx/
│ └── config
├── COPYING
├── README.md
├── cawbird.gresource.xml
├── data/
│ ├── cawbird.1
│ ├── meson.build
│ ├── meson_post_install.py
│ ├── render-icons.sh
│ ├── uk.co.ibboard.cawbird.appdata.xml.in
│ ├── uk.co.ibboard.cawbird.desktop.in
│ ├── uk.co.ibboard.cawbird.gschema.xml
│ └── uk.co.ibboard.cawbird.service.in
├── examples/
│ ├── accountdialog.vala
│ ├── meson.build
│ └── tweetstates.vala
├── flatpak/
│ └── uk.co.ibboard.cawbird.json
├── meson.build
├── meson_options.txt
├── notes.md
├── po/
│ ├── LINGUAS
│ ├── POTFILES.in
│ ├── POTFILES.skip
│ ├── ar.po
│ ├── ast.po
│ ├── ca.po
│ ├── ca@valencia.po
│ ├── cawbird.pot
│ ├── da.po
│ ├── de.po
│ ├── de_DE.po
│ ├── en_GB.po
│ ├── en_US.po
│ ├── eo.po
│ ├── es.po
│ ├── es_419.po
│ ├── es_MX.po
│ ├── es_VE.po
│ ├── fa.po
│ ├── fi.po
│ ├── fr.po
│ ├── ga.po
│ ├── gd.po
│ ├── gl.po
│ ├── hi.po
│ ├── hu.po
│ ├── id.po
│ ├── it.po
│ ├── ja.po
│ ├── ko.po
│ ├── lt.po
│ ├── meson.build
│ ├── nb.po
│ ├── nl.po
│ ├── pl.po
│ ├── pt.po
│ ├── pt_BR.po
│ ├── ro.po
│ ├── ru.po
│ ├── sr.po
│ ├── sr_BA@latin.po
│ ├── tr.po
│ ├── uk_UA.po
│ ├── zh_CN.po
│ └── zh_TW.po
├── sql/
│ ├── accounts/
│ │ ├── Create.1.sql
│ │ ├── Create.2.sql
│ │ ├── Create.3.sql
│ │ ├── Create.4.sql
│ │ ├── Create.5.sql
│ │ ├── Create.6.sql
│ │ └── Create.7.sql
│ └── init/
│ ├── Create.1.sql
│ ├── Create.2.sql
│ ├── Create.3.sql
│ └── Create.4.sql
├── src/
│ ├── Account.vala
│ ├── Cawbird.vala
│ ├── CbAvatarCache.c
│ ├── CbAvatarCache.h
│ ├── CbBundle.c
│ ├── CbBundle.h
│ ├── CbBundleHistory.c
│ ├── CbBundleHistory.h
│ ├── CbDeltaUpdater.c
│ ├── CbDeltaUpdater.h
│ ├── CbEmojiChooser.c
│ ├── CbEmojiChooser.h
│ ├── CbFilter.c
│ ├── CbFilter.h
│ ├── CbGtkCompat.h
│ ├── CbMedia.c
│ ├── CbMedia.h
│ ├── CbMediaDownloader.c
│ ├── CbMediaDownloader.h
│ ├── CbMediaImageWidget.c
│ ├── CbMediaImageWidget.h
│ ├── CbMediaVideoWidget.c
│ ├── CbMediaVideoWidget.h
│ ├── CbMessageReceiver.c
│ ├── CbMessageReceiver.h
│ ├── CbSnippetManager.c
│ ├── CbSnippetManager.h
│ ├── CbSurfaceProgress.c
│ ├── CbSurfaceProgress.h
│ ├── CbTextTransform.c
│ ├── CbTextTransform.h
│ ├── CbTweet.c
│ ├── CbTweet.h
│ ├── CbTweetModel.c
│ ├── CbTweetModel.h
│ ├── CbTwitterItem.c
│ ├── CbTwitterItem.h
│ ├── CbTypes.c
│ ├── CbTypes.h
│ ├── CbUserCompletionModel.c
│ ├── CbUserCompletionModel.h
│ ├── CbUserCounter.c
│ ├── CbUserCounter.h
│ ├── CbUserStream.c
│ ├── CbUserStream.h
│ ├── CbUtils.c
│ ├── CbUtils.h
│ ├── ComposedTweet.vala
│ ├── DMManager.vala
│ ├── DMPage.vala
│ ├── DMThreadsPage.vala
│ ├── DefaultTimeline.vala
│ ├── FavoritesTimeline.vala
│ ├── FilterPage.vala
│ ├── HomeTimeline.vala
│ ├── IPage.vala
│ ├── ListStatusesPage.vala
│ ├── ListsPage.vala
│ ├── MainWidget.vala
│ ├── MainWindow.vala
│ ├── MediaUpload.vala
│ ├── MentionsTimeline.vala
│ ├── NotificationManager.vala
│ ├── OAuthProxyCallWithBody.vala
│ ├── OAuthProxyCallWithQueryString.vala
│ ├── ProfilePage.vala
│ ├── SearchPage.vala
│ ├── Settings.vala
│ ├── TweetInfoPage.vala
│ ├── Twitter.vala
│ ├── UserEventReceiver.vala
│ ├── async/
│ │ ├── Collect.vala
│ │ └── CollectById.vala
│ ├── cawbird.vapi
│ ├── libtl/
│ │ ├── data.h
│ │ ├── libtweetlength.c
│ │ └── libtweetlength.h
│ ├── list/
│ │ ├── AddListEntry.vala
│ │ ├── DMListEntry.vala
│ │ ├── DMThreadEntry.vala
│ │ ├── FavImageRow.vala
│ │ ├── FilterListEntry.vala
│ │ ├── ListListEntry.vala
│ │ ├── NewListEntry.vala
│ │ ├── SnippetListEntry.vala
│ │ ├── StartConversationEntry.vala
│ │ ├── TweetListEntry.vala
│ │ ├── UserFilterEntry.vala
│ │ └── UserListEntry.vala
│ ├── main.vala
│ ├── model/
│ │ └── DMThreadsModel.vala
│ ├── sql/
│ │ ├── BaseStatement.vala
│ │ ├── Database.vala
│ │ ├── DeleteStatement.vala
│ │ ├── InsertStatement.vala
│ │ ├── SelectStatement.vala
│ │ └── UpdateStatement.vala
│ ├── util/
│ │ ├── Benchmark.vala
│ │ ├── Dirs.vala
│ │ ├── ListUtils.vala
│ │ ├── TweetUtils.vala
│ │ ├── UserCompletion.vala
│ │ ├── UserUtils.vala
│ │ └── Utils.vala
│ ├── widgets/
│ │ ├── AccountCreateWidget.vala
│ │ ├── AddImageButton.vala
│ │ ├── AspectImage.vala
│ │ ├── AvatarBannerWidget.vala
│ │ ├── AvatarWidget.vala
│ │ ├── BadgeRadioButton.vala
│ │ ├── CompletionTextView.vala
│ │ ├── ComposeImageManager.vala
│ │ ├── CropWidget.vala
│ │ ├── DMPlaceholderBox.vala
│ │ ├── DoubleTapButton.vala
│ │ ├── FavImageView.vala
│ │ ├── FollowButton.vala
│ │ ├── ImpostorWidget.vala
│ │ ├── LazyMenuButton.vala
│ │ ├── ListBox.vala
│ │ ├── MediaButton.vala
│ │ ├── MediaButtonSurface.vala
│ │ ├── MultiMediaWidget.vala
│ │ ├── PixbufButton.vala
│ │ ├── ReplyEntry.vala
│ │ ├── ResizableImage.vala
│ │ ├── ScrollWidget.vala
│ │ ├── TextButton.vala
│ │ ├── TweetListBox.vala
│ │ └── UserListsWidget.vala
│ └── window/
│ ├── AboutDialog.vala
│ ├── AccountDialog.vala
│ ├── ComposeTweetWindow.vala
│ ├── ImageDescriptionWindow.vala
│ ├── MediaDialog.vala
│ ├── ModifyFilterDialog.vala
│ ├── ModifySnippetDialog.vala
│ ├── SettingsDialog.vala
│ └── UserListDialog.vala
├── tests/
│ ├── avatarcache.vala
│ ├── avatardownload.vala
│ ├── bundlehistory.vala
│ ├── dmmanager.vala
│ ├── filters.vala
│ ├── friends.vala
│ ├── inlinemediadownloader.vala
│ ├── meson.build
│ ├── texttransform.vala
│ ├── tweetmodel.vala
│ ├── tweetparsing.vala
│ ├── twitteritem.vala
│ ├── usercompletionmodel.vala
│ ├── usercounter.vala
│ └── utils.vala
├── ui/
│ ├── about-dialog.ui
│ ├── account-create-widget.ui
│ ├── account-dialog.ui
│ ├── cb-emoji-chooser.ui
│ ├── compose-window.ui
│ ├── dm-page.ui
│ ├── dm-thread-entry.ui
│ ├── filter-list-entry.ui
│ ├── filter-page.ui
│ ├── image-description-window.ui
│ ├── list-list-entry.ui
│ ├── list-statuses-page.ui
│ ├── media-dialog.ui
│ ├── menus.ui
│ ├── modify-filter-dialog.ui
│ ├── modify-snippet-dialog.ui
│ ├── new-list-entry.ui
│ ├── profile-page.ui
│ ├── search-page.ui
│ ├── settings-dialog.ui
│ ├── shortcuts-window.ui
│ ├── start-conversation-entry.ui
│ ├── style.css
│ ├── tweet-info-page.ui
│ ├── tweet-list-entry.ui
│ ├── user-filter-entry.ui
│ ├── user-list-entry.ui
│ └── user-lists-widget.ui
└── vapi/
├── cawbird-internal.vapi
├── config.vapi
└── libtl.vapi
SYMBOL INDEX (407 symbols across 52 files)
FILE: sql/accounts/Create.1.sql
type `common` (line 4) | CREATE TABLE IF NOT EXISTS `common`(
type `info` (line 10) | CREATE TABLE IF NOT EXISTS `info`(
type `dm_threads` (line 17) | CREATE TABLE IF NOT EXISTS `dm_threads`(
type `dms` (line 26) | CREATE TABLE IF NOT EXISTS `dms` (
type `user_cache` (line 39) | CREATE TABLE IF NOT EXISTS `user_cache`(
FILE: sql/accounts/Create.2.sql
type `filters` (line 3) | CREATE TABLE IF NOT EXISTS `filters`(
FILE: sql/init/Create.1.sql
type `accounts` (line 4) | CREATE TABLE IF NOT EXISTS `accounts`(
FILE: sql/init/Create.2.sql
type `snippets` (line 4) | CREATE TABLE IF NOT EXISTS `snippets`(
FILE: sql/init/Create.3.sql
type `info` (line 6) | CREATE TABLE IF NOT EXISTS `info`(
FILE: src/CbAvatarCache.c
type CacheEntry (line 23) | typedef struct _CacheEntry CacheEntry;
type _CacheEntry (line 24) | struct _CacheEntry
function cache_entry_destroy (line 32) | static void
function CacheEntry (line 41) | static inline CacheEntry *
function CbAvatarCache (line 58) | CbAvatarCache *
function cb_avatar_cache_add (line 64) | void
function cb_avatar_cache_set_avatar (line 103) | void
function cairo_surface_t (line 128) | cairo_surface_t *
function cb_avatar_cache_set_url (line 154) | void
function cb_avatar_cache_decrease_refcount_for_surface (line 173) | void
function cb_avatar_cache_increase_refcount_for_surface (line 211) | void
function guint (line 249) | guint
function cb_avatar_cache_finalize (line 257) | static void
function cb_avatar_cache_init (line 267) | static void
function cb_avatar_cache_class_init (line 274) | static void
FILE: src/CbAvatarCache.h
type _CbAvatarCache (line 26) | struct _CbAvatarCache
type _CbAvatarCache (line 27) | struct _CbAvatarCache
FILE: src/CbBundle.c
function CbBundle (line 24) | CbBundle *
function GValue (line 30) | static GValue *
function guint (line 48) | guint
function cb_bundle_put_string (line 58) | void
function cb_bundle_put_int (line 97) | void
function cb_bundle_get_int (line 119) | int
function cb_bundle_put_int64 (line 135) | void
function gint64 (line 157) | gint64
function cb_bundle_put_bool (line 173) | void
function gboolean (line 195) | gboolean
function cb_bundle_put_object (line 211) | void
function GObject (line 233) | GObject *
function gboolean (line 249) | gboolean
function cb_bundle_finalize (line 290) | static void
function cb_bundle_class_init (line 312) | static void
function cb_bundle_init (line 320) | static void
FILE: src/CbBundle.h
type _CbBundle (line 31) | struct _CbBundle
type CbBundle (line 39) | typedef struct _CbBundle CbBundle;
FILE: src/CbBundleHistory.c
function cb_bundle_history_finalize (line 24) | static void
function cb_bundle_history_init (line 39) | static void
function cb_bundle_history_class_init (line 50) | static void
function CbBundleHistory (line 58) | CbBundleHistory *
function cb_bundle_history_push (line 64) | void
function cb_bundle_history_back (line 85) | int
function cb_bundle_history_forward (line 97) | int
function gboolean (line 109) | gboolean
function gboolean (line 115) | gboolean
function cb_bundle_history_remove_current (line 129) | void
function cb_bundle_history_get_current (line 152) | int
function CbBundle (line 161) | CbBundle *
FILE: src/CbBundleHistory.h
type _CbBundleHistory (line 26) | struct _CbBundleHistory
type CbBundleHistory (line 35) | typedef struct _CbBundleHistory CbBundleHistory;
FILE: src/CbDeltaUpdater.c
function gboolean (line 23) | static gboolean
function cb_delta_updater_finalize (line 75) | static void
function cb_delta_updater_init (line 86) | static void
function cb_delta_updater_class_init (line 92) | static void
function CbDeltaUpdater (line 100) | CbDeltaUpdater *
FILE: src/CbDeltaUpdater.h
type CbDeltaUpdater (line 25) | typedef struct _CbDeltaUpdater CbDeltaUpdater;
type CbDeltaUpdaterClass (line 26) | typedef struct _CbDeltaUpdaterClass CbDeltaUpdaterClass;
type _CbDeltaUpdater (line 35) | struct _CbDeltaUpdater
type _CbDeltaUpdaterClass (line 43) | struct _CbDeltaUpdaterClass
FILE: src/CbEmojiChooser.c
function scroll_to_section (line 36) | static void
function populate_recent_section (line 67) | static void
function add_recent_item (line 90) | static void
function emoji_activated (line 133) | static void
function add_emoji (line 155) | static void
type PopulateData (line 202) | typedef struct {
function gboolean (line 209) | static gboolean
function populate_emoji_chooser (line 257) | static void
function adj_value_changed (line 273) | static void
function gboolean (line 323) | static gboolean
function invalidate_section (line 356) | static void
function update_headings (line 363) | static void
function search_changed (line 395) | static void
function setup_section (line 415) | static void
function cb_emoji_chooser_finalize (line 446) | static void
function cb_emoji_chooser_init (line 462) | static void
function cb_emoji_chooser_class_init (line 491) | static void
function GtkWidget (line 556) | GtkWidget *
function cb_emoji_chooser_populate (line 562) | void
function gboolean (line 572) | gboolean
FILE: src/CbEmojiChooser.h
type EmojiSection (line 23) | typedef struct {
type _CbEmojiChooser (line 32) | struct _CbEmojiChooser
type CbEmojiChooser (line 58) | typedef struct _CbEmojiChooser CbEmojiChooser;
FILE: src/CbFilter.c
function cb_filter_finalize (line 23) | static void
function cb_filter_init (line 35) | static void
function cb_filter_class_init (line 42) | static void
function CbFilter (line 50) | CbFilter *
function cb_filter_reset (line 60) | void
function gboolean (line 73) | gboolean
function cb_filter_get_id (line 97) | int
function cb_filter_set_id (line 105) | void
FILE: src/CbFilter.h
type _CbFilter (line 25) | struct _CbFilter
type _CbFilter (line 26) | struct _CbFilter
FILE: src/CbGtkCompat.h
function gtk_widget_measure (line 23) | void gtk_widget_measure (GtkWidget *widget,
FILE: src/CbMedia.c
function cb_media_finalize (line 31) | static void
function cb_media_class_init (line 65) | static void
function cb_media_init (line 86) | static void
function CbMedia (line 112) | CbMedia *
function gboolean (line 118) | gboolean
function gboolean (line 135) | gboolean
function gboolean (line 140) | static gboolean
function cb_media_update_progress (line 152) | void
function cb_media_loading_finished (line 165) | void
function CbMediaType (line 198) | CbMediaType
function gboolean (line 210) | static gboolean
function cb_media_update_hires_progress (line 222) | void
function cb_media_loading_hires_finished (line 235) | void
function cairo_surface_t (line 251) | cairo_surface_t *
FILE: src/CbMedia.h
type _CbMedia (line 38) | struct _CbMedia
type CbMedia (line 72) | typedef struct _CbMedia CbMedia;
FILE: src/CbMediaDownloader.c
type LoadingData (line 27) | typedef struct {
function loading_data_free (line 32) | static void
function CbMediaDownloader (line 40) | CbMediaDownloader *
function mark_invalid (line 53) | static void
function load_animation (line 82) | static void
function load_media_url (line 131) | static void
function cb_media_downloader_get_instagram_url (line 194) | static void
function cb_media_downloader_load_twitter_video (line 213) | static void
function cb_media_downloader_load_real_url (line 266) | static void
function update_media_progress (line 297) | static void
function cb_media_downloader_load_threaded (line 311) | static void
function load_in_thread (line 384) | void
function cb_media_downloader_load_async (line 399) | void
function cb_media_downloader_reload_async (line 424) | void cb_media_downloader_reload_async (CbMediaDownloader *downloader,
function update_media_hires_progress (line 441) | static void
function cb_media_downloader_load_hires_threaded (line 455) | static void
function load_hires_in_thread (line 480) | void
function cb_media_downloader_load_hires_async (line 495) | void
function gboolean (line 522) | gboolean
function cb_media_downloader_load_all (line 532) | void
function cb_media_downloader_disable (line 546) | void
function cb_media_downloader_shutdown (line 554) | void
function gboolean (line 566) | gboolean
function gboolean (line 589) | gboolean
function cb_media_downloader_init (line 605) | static void
function cb_media_downloader_class_init (line 612) | static void
function GQuark (line 617) | GQuark
FILE: src/CbMediaDownloader.h
function G_BEGIN_DECLS (line 26) | G_BEGIN_DECLS
type CbMediaDownloader (line 36) | typedef struct _CbMediaDownloader CbMediaDownloader;
FILE: src/CbMediaImageWidget.c
function cb_media_image_widget_finalize (line 21) | static void
function drag_begin_cb (line 39) | static void
function drag_update_cb (line 57) | static void
function cb_media_image_widget_class_init (line 75) | static void
function cb_media_image_widget_init (line 83) | static void
function set_window_size_request (line 96) | void
function hires_progress (line 118) | void
function GtkWidget (line 130) | GtkWidget *
FILE: src/CbMediaImageWidget.h
type _CbMediaImageWidget (line 28) | struct _CbMediaImageWidget
type CbMediaImageWidget (line 45) | typedef struct _CbMediaImageWidget CbMediaImageWidget;
FILE: src/CbMediaVideoWidget.c
function cb_media_video_widget_show_error (line 24) | static void
function cb_media_video_widget_start_video (line 32) | static void
function cb_media_video_widget_stop_video (line 43) | static void
function soup_message_received_cb (line 59) | static void
function cancelled_cb (line 104) | static void
function fetch_real_url (line 117) | static void
function gboolean (line 129) | static gboolean
function gboolean (line 152) | static gboolean
function cb_media_video_widget_destroy (line 214) | static void
function gboolean (line 223) | static gboolean
function cb_media_video_widget_finalize (line 234) | static void
function cb_media_video_widget_init (line 252) | static void
function cb_media_video_widget_class_init (line 319) | static void
function CbMediaVideoWidget (line 331) | CbMediaVideoWidget *
function cb_media_video_widget_start (line 387) | void
FILE: src/CbMediaVideoWidget.h
type _CbMediaVideoWidget (line 31) | struct _CbMediaVideoWidget
type CbMediaVideoWidget (line 52) | typedef struct _CbMediaVideoWidget CbMediaVideoWidget;
FILE: src/CbMessageReceiver.c
function cb_message_receiver_default_init (line 22) | static void
function cb_message_receiver_stream_message_received (line 28) | void
FILE: src/CbMessageReceiver.h
type _CbMessageReceiverInterface (line 29) | struct _CbMessageReceiverInterface
FILE: src/CbSnippetManager.c
function load_snippet_cb (line 25) | static int
function cb_snippet_manager_load_snippets (line 35) | static void
function cb_snippet_manager_finalize (line 56) | static void
function cb_snippet_manager_class_init (line 66) | static void
function CbSnippetManager (line 74) | CbSnippetManager *
function cb_snippet_manager_init (line 84) | static void
function guint (line 91) | guint
function cb_snippet_manager_remove_snippet (line 100) | void
function cb_snippet_manager_insert_snippet (line 122) | void
function gboolean (line 147) | static gboolean
function gboolean (line 161) | gboolean
function cb_snippet_manager_query_snippets (line 190) | void
function cb_snippet_manager_set_snippet (line 201) | void
FILE: src/CbSnippetManager.h
type _CbSnippetManager (line 25) | struct _CbSnippetManager
type CbSnippetManager (line 33) | typedef struct _CbSnippetManager CbSnippetManager;
FILE: src/CbSurfaceProgress.c
function gboolean (line 22) | static gboolean
function cb_surface_progress_get_preferred_width (line 88) | static void
function cb_surface_progress_get_preferred_height (line 96) | static void
function cb_surface_progress_finalize (line 104) | static void
function cb_surface_progress_init (line 115) | static void
function cb_surface_progress_class_init (line 121) | static void
function GtkWidget (line 134) | GtkWidget *
function cb_surface_progress_get_progress (line 140) | double
function cb_surface_progress_set_progress (line 146) | void
function cairo_surface_t (line 161) | cairo_surface_t *
function cb_surface_progress_set_surface (line 167) | void
FILE: src/CbSurfaceProgress.h
type _CbSurfaceProgress (line 25) | struct _CbSurfaceProgress
type CbSurfaceProgress (line 32) | typedef struct _CbSurfaceProgress CbSurfaceProgress;
FILE: src/CbTextTransform.c
function gboolean (line 42) | static inline gboolean
function gboolean (line 48) | static inline gboolean
function gboolean (line 54) | static inline gboolean
function gboolean (line 60) | static inline gboolean
function gboolean (line 69) | static inline gboolean
FILE: src/CbTextTransform.h
type CbTransformFlags (line 24) | typedef enum {
FILE: src/CbTweet.c
function gboolean (line 24) | static gboolean
function gboolean (line 44) | gboolean
function gboolean (line 63) | gboolean
function gboolean (line 72) | gboolean
function gboolean (line 83) | gboolean
function gint64 (line 92) | gint64
function CbMedia (line 127) | CbMedia **
function CbMedia (line 146) | CbMedia **
function cb_tweet_load_from_json (line 202) | void
function gboolean (line 346) | gboolean
function gboolean (line 352) | gboolean
function cb_tweet_set_flag (line 358) | void
function cb_tweet_unset_flag (line 373) | void
function gboolean (line 388) | gboolean
function cb_tweet_set_quoted_flag (line 394) | void
function cb_tweet_unset_quoted_flag (line 409) | void
function gboolean (line 498) | gboolean
function cb_tweet_set_seen (line 506) | void
function CbUserIdentity (line 524) | CbUserIdentity *
function CbTweet (line 546) | CbTweet *
function cb_tweet_finalize (line 552) | static void
function cb_tweet_init (line 581) | static void
function cb_tweet_class_init (line 591) | static void
FILE: src/CbTweet.h
type CbTweetState (line 28) | typedef enum
type _CbTweet (line 68) | struct _CbTweet
type CbTweet (line 93) | typedef struct _CbTweet CbTweet;
FILE: src/CbTweetModel.c
function GType (line 25) | static GType
function guint (line 31) | static guint
function gpointer (line 39) | static gpointer
function cb_tweet_model_iface_init (line 53) | static void
function emit_items_changed (line 61) | static inline void
function cb_tweet_model_init (line 70) | static void
function cb_tweet_model_finalize (line 80) | static void
function cb_tweet_model_class_init (line 91) | static void
function CbTweetModel (line 99) | CbTweetModel *
function update_min_max_id (line 105) | static inline void
function cb_tweet_model_index_of (line 165) | int
function cb_tweet_model_index_of_retweet (line 183) | int
function remove_tweet_at_pos (line 201) | static void
function insert_sorted (line 216) | static inline void
function hide_tweet_internal (line 289) | static void
function show_tweet_internal (line 305) | static void
function gboolean (line 317) | gboolean
function cb_tweet_model_clear (line 324) | void
function cb_tweet_model_set_thread_mode (line 340) | void
function CbTweet (line 349) | CbTweet *
function gboolean (line 373) | gboolean
function cb_tweet_model_remove_tweet (line 406) | void
function cb_tweet_model_toggle_flag_on_user_tweets (line 452) | void
function cb_tweet_model_toggle_flag_on_user_retweets (line 501) | void
function gboolean (line 552) | gboolean
function gboolean (line 623) | gboolean
function cb_tweet_model_add (line 691) | void
function cb_tweet_model_remove_oldest_n_visible (line 710) | void
function cb_tweet_model_remove_tweets_later_than (line 743) | void
FILE: src/CbTweetModel.h
type CbTweetModel (line 27) | typedef struct _CbTweetModel CbTweetModel;
type CbTweetModelClass (line 28) | typedef struct _CbTweetModelClass CbTweetModelClass;
type _CbTweetModel (line 37) | struct _CbTweetModel
type _CbTweetModelClass (line 49) | struct _CbTweetModelClass
FILE: src/CbTwitterItem.c
function default_update_time_delta (line 24) | static int
function cb_twitter_item_default_init (line 32) | static void
function gint64 (line 42) | gint64
function cb_twitter_item_update_time_delta (line 54) | int
function gint64 (line 67) | gint64
function cb_twitter_item_set_last_set_timediff (line 79) | void
function GTimeSpan (line 92) | GTimeSpan
FILE: src/CbTwitterItem.h
type _CbTwitterItemInterface (line 27) | struct _CbTwitterItemInterface
FILE: src/CbTypes.c
function cb_user_identity_free (line 24) | void
function cb_user_identity_copy (line 31) | void
function cb_user_identity_parse (line 42) | void cb_user_identity_parse (CbUserIdentity *id,
function cb_text_entity_free (line 52) | void
function cb_text_entity_copy (line 61) | void
function cb_mini_tweet_free (line 78) | void
function cb_mini_tweet_copy (line 102) | void
function cb_mini_tweet_init (line 126) | void
function cb_mini_tweet_parse (line 138) | void
function json_object_get_member_size (line 194) | static int
function cb_mini_tweet_parse_entities (line 204) | void
FILE: src/CbTypes.h
type CbStreamMessageType (line 25) | typedef enum {
type _CbUserIdentity (line 66) | struct _CbUserIdentity
type CbUserIdentity (line 74) | typedef struct _CbUserIdentity CbUserIdentity;
type _CbTextEntity (line 80) | struct _CbTextEntity
type CbTextEntity (line 90) | typedef struct _CbTextEntity CbTextEntity;
type _CbMiniTweet (line 94) | struct _CbMiniTweet
type CbMiniTweet (line 113) | typedef struct _CbMiniTweet CbMiniTweet;
FILE: src/CbUserCompletionModel.c
function GType (line 26) | static GType
function guint (line 32) | static guint
function gpointer (line 40) | static gpointer
function cb_user_completion_model_iface_init (line 52) | static void
function cb_user_completion_model_init (line 60) | static void
function cb_user_completion_model_finalize (line 67) | static void
function cb_user_completion_model_class_init (line 77) | static void
function CbUserCompletionModel (line 85) | CbUserCompletionModel *
function gboolean (line 91) | static inline gboolean
function emit_items_changed (line 109) | static inline void
function cb_user_completion_model_insert_items (line 119) | void
function cb_user_completion_model_insert_infos (line 157) | void
function cb_user_completion_model_clear (line 196) | void
FILE: src/CbUserCompletionModel.h
type _CbUserCompletionModel (line 26) | struct _CbUserCompletionModel
type CbUserCompletionModel (line 33) | typedef struct _CbUserCompletionModel CbUserCompletionModel;
FILE: src/CbUserCounter.c
function cb_user_info_destroy (line 23) | void
function score_sort (line 30) | static int
function CbUserCounter (line 42) | CbUserCounter *
function cb_user_counter_id_seen (line 49) | void
function user_seen (line 59) | void
function cb_user_counter_user_seen (line 112) | void
function cb_user_counter_user_seen_full (line 121) | void
function cb_user_counter_save (line 132) | int
function cb_user_counter_query_by_prefix (line 188) | void
function cb_user_counter_finalize (line 328) | static void
function cb_user_counter_class_init (line 338) | static void
function cb_user_counter_init (line 346) | static void
FILE: src/CbUserCounter.h
type _CbUserInfo (line 29) | struct _CbUserInfo
type _CbUserInfo (line 30) | struct _CbUserInfo
type CbUserCOunter (line 42) | typedef struct _CbUserCounter CbUserCOunter;
type _CbUserCounter (line 43) | struct _CbUserCounter
FILE: src/CbUserStream.c
function cb_user_stream_finalize (line 48) | static void
function cb_user_stream_restart (line 66) | static void
function gboolean (line 74) | static gboolean
function start_network_timeout (line 99) | static void
function network_changed_cb (line 108) | static void
function cb_user_stream_init (line 135) | static void
function cb_user_stream_class_init (line 153) | static void
function CbUserStream (line 175) | CbUserStream *
function stream_tweet (line 187) | void
function cb_user_stream_inject_tweet (line 215) | void
function load_timeline_tweets_done (line 297) | void
function gboolean (line 341) | gboolean
function load_mentions_tweets_done (line 384) | void
function gboolean (line 428) | gboolean
function load_favourited_tweets_done (line 462) | void
function gboolean (line 506) | gboolean
function load_dm_tweets_done (line 544) | void
function load_dm_tweets_with_cursor (line 639) | void
function gboolean (line 662) | gboolean
function cb_user_stream_start (line 669) | void
function cb_user_stream_stop (line 699) | void cb_user_stream_stop (CbUserStream *self)
function cb_user_stream_set_proxy_data (line 719) | void
function cb_user_stream_register (line 730) | void
function cb_user_stream_unregister (line 737) | void
FILE: src/CbUserStream.h
type _CbUserStream (line 32) | struct _CbUserStream
type CbUserStream (line 70) | typedef struct _CbUserStream CbUserStream;
FILE: src/CbUtils.c
function cb_utils_bind_model (line 23) | void
type ModelData (line 42) | typedef struct {
function non_gobject_model_changed (line 48) | static void
function cb_utils_bind_non_gobject_model (line 92) | void
function cb_utils_unbind_non_gobject_model (line 115) | void
function cb_utils_linkify_user (line 132) | void
function GDateTime (line 288) | GDateTime *
function parse_json_async (line 469) | static void
function call_done_cb (line 502) | static void
function cb_utils_load_threaded_async (line 531) | void
function JsonNode (line 552) | JsonNode *
function users_received_cb (line 562) | static void
function cb_utils_query_users_async (line 619) | void
function CbUserIdentity (line 644) | CbUserIdentity *
FILE: src/CbUtils.h
type GtkWidget (line 33) | typedef GtkWidget * (*CbUtilsCreateWidgetFunc) (gpointer *data, gpointer...
function cb_clear_source (line 82) | static inline void
FILE: src/libtl/libtweetlength.c
type Token (line 35) | typedef struct {
type CharTypeOption (line 149) | typedef struct _CharTypeOption {
function CharTypeOption (line 154) | static inline CharTypeOption*
function GHashTable (line 162) | static inline GHashTable*
function gboolean (line 255) | static gboolean
function guint (line 283) | static inline guint
function gboolean (line 342) | static inline gboolean
function gboolean (line 369) | static inline gboolean
function emplace_token (line 391) | static inline void
function emplace_entity_for_tokens (line 412) | static inline void
function gboolean (line 439) | static inline gboolean
function gboolean (line 450) | static inline gboolean
function gboolean (line 477) | static inline gboolean
function gboolean (line 492) | static inline gboolean
function gsize (line 538) | static inline gsize
function gboolean (line 550) | static inline gboolean
function guint (line 564) | static inline guint
function GArray (line 768) | static GArray *
function gboolean (line 883) | static gboolean
function gboolean (line 944) | static gboolean
function gboolean (line 1114) | static gboolean
function gboolean (line 1209) | static gboolean
function GArray (line 1274) | static GArray *
function gsize (line 1329) | static gsize
function gsize (line 1350) | gsize
function gsize (line 1367) | gsize
function gsize (line 1396) | static inline gsize
function gsize (line 1408) | static gsize
function gsize (line 1432) | gsize
function gsize (line 1472) | gsize
function TlEntity (line 1514) | TlEntity *
function TlEntity (line 1537) | static TlEntity *
function TlEntity (line 1620) | TlEntity *
function TlEntity (line 1663) | TlEntity *
function TlEntity (line 1706) | TlEntity *
FILE: src/libtl/libtweetlength.h
type _TlEntity (line 23) | struct _TlEntity {
type TlEntity (line 32) | typedef struct _TlEntity TlEntity;
type TlEntityType (line 34) | typedef enum {
type TlCountType (line 42) | typedef enum {
Condensed preview — 265 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,210K chars).
[
{
"path": "._vimrc",
"chars": 98,
"preview": "set wildignore+=*.c,*\\~,CMakeFiles,Makefile,*.lo,test-driver,*.trs,*.stamp,Makefile.in,*.la,*.svg\n"
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.md",
"chars": 792,
"preview": "---\nname: Bug report\nabout: Create a report to help us fix problems and errors\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n"
},
{
"path": ".github/ISSUE_TEMPLATE/feature_request.md",
"chars": 606,
"preview": "---\nname: Feature request\nabout: Suggest an idea for a change or new feature\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**"
},
{
"path": ".github/workflows/main.yml",
"chars": 348,
"preview": "name: GitHub Polls Actions Bot\n\non:\n issue_comment:\n types: [created, edited] # issue comment is created or edited\n "
},
{
"path": ".gitignore",
"chars": 125,
"preview": "# Build Directories\nbuild/\n_build/\nflatpak/_build\nflatpak/.flatpak-builder\nvalgrind*\ndata/consumer_k.dat\ndata/consumer_s"
},
{
"path": ".tx/config",
"chars": 261,
"preview": "[main]\nhost = https://transifex.com\n\n[corebird.corebirdpot]\nfile_filter = po/<lang>.po\nhost = https://transifex.com\nsour"
},
{
"path": "COPYING",
"chars": 35147,
"preview": " GNU GENERAL PUBLIC LICENSE\n Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
},
{
"path": "README.md",
"chars": 15362,
"preview": "# Cawbird 1.5\n\n## DEPRECATION NOTICE\n\n⚠ As of January 2023, Cawbird for Twitter is no longer being developed ⚠\n\nThis is "
},
{
"path": "cawbird.gresource.xml",
"chars": 3949,
"preview": "<gresources>\n <gresource prefix=\"/uk/co/ibboard/cawbird\">\n <file preprocess=\"xml-stripblanks\" alias=\"gtk/menus.ui\">u"
},
{
"path": "data/cawbird.1",
"chars": 1251,
"preview": ".TH \"cawbird\" \"1\" \"08. Feb. 2014\" \"man page by Malcolm J Lewis\" \"\"\n.SH NAME\n.B\ncawbird\n- Native Gtk+ Twitter client for "
},
{
"path": "data/meson.build",
"chars": 1262,
"preview": "i18n = import('i18n')\n\ninstall_data(\n 'uk.co.ibboard.cawbird.gschema.xml',\n install_dir: join_paths(get_option('datadi"
},
{
"path": "data/meson_post_install.py",
"chars": 282,
"preview": "#!/usr/bin/env python3\n\nimport os\nimport subprocess\n\nschemadir = os.path.join(os.environ['MESON_INSTALL_PREFIX'], 'share"
},
{
"path": "data/render-icons.sh",
"chars": 327,
"preview": "#!/bin/bash\n\nsizes=(16 24 32 48 64 96)\n\nfor size in ${sizes[@]}\ndo\n rsvg-convert ./uk.co.ibboard.cawbird.svg --width=\""
},
{
"path": "data/uk.co.ibboard.cawbird.appdata.xml.in",
"chars": 22923,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!-- Copyright 2013 Ryan Lerch <ryanlerch@fedoraproject.org> -->\n<component type="
},
{
"path": "data/uk.co.ibboard.cawbird.desktop.in",
"chars": 630,
"preview": "[Desktop Entry]\nName=Cawbird\nGenericName=Twitter Client\nComment=Use Twitter from within a normal desktop application\n# T"
},
{
"path": "data/uk.co.ibboard.cawbird.gschema.xml",
"chars": 6472,
"preview": "<schemalist>\n <enum id=\"uk.co.ibboard.cawbird.tweet-stack\">\n <value nick=\"Never\" value=\"0\" />\n <value nick=\"E"
},
{
"path": "data/uk.co.ibboard.cawbird.service.in",
"chars": 88,
"preview": "[D-BUS Service]\nName=uk.co.ibboard.cawbird\nExec=@bindir@/cawbird --gapplication-service\n"
},
{
"path": "examples/accountdialog.vala",
"chars": 249,
"preview": "\n\n\nvoid main (string[] args) {\n Gtk.init (ref args);\n\n Utils.load_custom_css ();\n Settings.init ();\n var acc = new A"
},
{
"path": "examples/meson.build",
"chars": 236,
"preview": "executable('tweetstates',\n 'tweetstates.vala',\n cb_resources,\n dependencies: cb_dep,\n vala_args: [\n meson.source_"
},
{
"path": "examples/tweetstates.vala",
"chars": 115432,
"preview": "\nCb.Tweet parse_tweet (string input) {\n var parser = new Json.Parser ();\n try {\n parser.load_from_data (input);\n }"
},
{
"path": "flatpak/uk.co.ibboard.cawbird.json",
"chars": 2463,
"preview": "{\n \"app-id\":\"uk.co.ibboard.cawbird\",\n \"runtime\":\"org.gnome.Platform\",\n \"runtime-version\":\"master\",\n \"sdk\":\"org.gnome"
},
{
"path": "meson.build",
"chars": 7850,
"preview": "project('Cawbird', ['vala', 'c'],\n version: '1.5',\n default_options: [\n 'buildtype=debug'\n "
},
{
"path": "meson_options.txt",
"chars": 682,
"preview": "option('video', type: 'boolean', value: 'true')\noption('spellcheck', type: 'boolean', value: 'true')\noption('exampl"
},
{
"path": "notes.md",
"chars": 5395,
"preview": "# Notes\n\nThis file contains a variety of development notes that track how some bits of the code work.\nThis could be incl"
},
{
"path": "po/LINGUAS",
"chars": 163,
"preview": "ar\nast\nca\nca@valencia\nda\nde\nde_DE\nen_GB\neo\nes\nes_419\nes_MX\nes_VE\nfa\nfi\nfr\nga\ngd\ngl\nhi\nhu\nid\nit\nja\nko\nlt\nnb\nnl\npl\npt\npt_B"
},
{
"path": "po/POTFILES.in",
"chars": 1803,
"preview": "# List of source files containing translatable strings.\n# Please keep this file sorted alphabetically.\ndata/uk.co.ibboar"
},
{
"path": "po/POTFILES.skip",
"chars": 881,
"preview": "# List of source files that should *not* be translated.\n# Please keep this file sorted alphabetically.\nsrc/DefaultTimeli"
},
{
"path": "po/ar.po",
"chars": 25227,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "po/ast.po",
"chars": 25352,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "po/ca.po",
"chars": 25529,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER\n# This file is distributed under the same "
},
{
"path": "po/ca@valencia.po",
"chars": 21749,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "po/cawbird.pot",
"chars": 19424,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR 2013-2018 Timm Bäder, 2018-2020 IBBoard\n# This file is distributed under "
},
{
"path": "po/da.po",
"chars": 27105,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR 2013-2018 Timm Bäder, 2018-2020 IBBoard\n# This file is distributed under "
},
{
"path": "po/de.po",
"chars": 25820,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "po/de_DE.po",
"chars": 25833,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "po/en_GB.po",
"chars": 26914,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR 2013-2018 Timm Bäder, 2018-2020 IBBoard\n# This file is distributed under "
},
{
"path": "po/en_US.po",
"chars": 26403,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR 2013-2018 Timm Bäder, 2018-2020 IBBoard\n# This file is distributed under "
},
{
"path": "po/eo.po",
"chars": 24852,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "po/es.po",
"chars": 29140,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR 2013-2018 Timm Bäder, 2018-2020 IBBoard\n# This file is distributed under "
},
{
"path": "po/es_419.po",
"chars": 28577,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR 2013-2018 Timm Bäder, 2018-2020 IBBoard\n# This file is distributed under "
},
{
"path": "po/es_MX.po",
"chars": 28113,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR 2013-2018 Timm Bäder, 2018-2020 IBBoard\n# This file is distributed under "
},
{
"path": "po/es_VE.po",
"chars": 28345,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR 2013-2018 Timm Bäder, 2018-2020 IBBoard\n# This file is distributed under "
},
{
"path": "po/fa.po",
"chars": 20573,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "po/fi.po",
"chars": 27360,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR 2013-2018 Timm Bäder, 2018-2022 IBBoard\n# This file is distributed under "
},
{
"path": "po/fr.po",
"chars": 29840,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR 2013-2018 Timm Bäder, 2018-2020 IBBoard\n# This file is distributed under "
},
{
"path": "po/ga.po",
"chars": 20886,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "po/gd.po",
"chars": 31006,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR 2013-2018 Timm Bäder, 2018-2020 IBBoard\n# This file is distributed under "
},
{
"path": "po/gl.po",
"chars": 24961,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "po/hi.po",
"chars": 20331,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "po/hu.po",
"chars": 25530,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR 2013-2018 Timm Bäder, 2018-2020 IBBoard\n# This file is distributed under "
},
{
"path": "po/id.po",
"chars": 24474,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "po/it.po",
"chars": 28725,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR 2013-2018 Timm Bäder, 2018-2020 IBBoard\n# This file is distributed under "
},
{
"path": "po/ja.po",
"chars": 21339,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "po/ko.po",
"chars": 21379,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "po/lt.po",
"chars": 26003,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "po/meson.build",
"chars": 349,
"preview": "i18n = import('i18n')\n\ni18n.gettext('cawbird', args: [\n '--keyword=_',\n '--keyword=N_',\n '--flag=N_:1:pass-c-fo"
},
{
"path": "po/nb.po",
"chars": 26526,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR 2013-2018 Timm Bäder, 2018-2020 IBBoard\n# This file is distributed under "
},
{
"path": "po/nl.po",
"chars": 28411,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR 2013-2018 Timm Bäder, 2018-2020 IBBoard\n# This file is distributed under "
},
{
"path": "po/pl.po",
"chars": 26442,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "po/pt.po",
"chars": 27681,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR 2013-2018 Timm Bäder, 2018-2020 IBBoard\n# This file is distributed under "
},
{
"path": "po/pt_BR.po",
"chars": 28114,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR 2013-2018 Timm Bäder, 2018-2020 IBBoard\n# This file is distributed under "
},
{
"path": "po/ro.po",
"chars": 22371,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "po/ru.po",
"chars": 28362,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR 2013-2018 Timm Bäder, 2018-2020 IBBoard\n# This file is distributed under "
},
{
"path": "po/sr.po",
"chars": 25599,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "po/sr_BA@latin.po",
"chars": 25575,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "po/tr.po",
"chars": 22338,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "po/uk_UA.po",
"chars": 23099,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "po/zh_CN.po",
"chars": 21211,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "po/zh_TW.po",
"chars": 21702,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR Timm Bäder\n# This file is distributed under the same license as the cawbi"
},
{
"path": "sql/accounts/Create.1.sql",
"chars": 1057,
"preview": "PRAGMA user_version = 1;\n\n-- SQL schema for an account database\nCREATE TABLE IF NOT EXISTS `common`(\n token VARCHAR(100"
},
{
"path": "sql/accounts/Create.2.sql",
"chars": 130,
"preview": "PRAGMA user_version = 2;\n\nCREATE TABLE IF NOT EXISTS `filters`(\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n content VARCHA"
},
{
"path": "sql/accounts/Create.3.sql",
"chars": 73,
"preview": "PRAGMA user_version = 3;\n\nALTER TABLE `info`\nADD last_tweet VARCHAR(255)\n"
},
{
"path": "sql/accounts/Create.4.sql",
"chars": 164,
"preview": "PRAGMA user_version = 4;\n\nALTER TABLE `info`\nADD last_tweet_reply_id NUMERIC(19,0) DEFAULT 0;\n\nALTER TABLE `info`\nADD la"
},
{
"path": "sql/accounts/Create.5.sql",
"chars": 300,
"preview": "PRAGMA user_version = 5;\n\nALTER TABLE `info`\nADD last_tweet_image_1 TEXT NOT NULL DEFAULT \"\";\n\nALTER TABLE `info`\nADD la"
},
{
"path": "sql/accounts/Create.6.sql",
"chars": 170,
"preview": "PRAGMA user_version = 6;\n\nALTER TABLE `user_cache`\nADD verified INTEGER(1) NOT NULL DEFAULT 0;\n\nALTER TABLE `user_cache`"
},
{
"path": "sql/accounts/Create.7.sql",
"chars": 77,
"preview": "PRAGMA user_version = 7;\n\nALTER TABLE `dms`\nADD message_json TEXT DEFAULT '';"
},
{
"path": "sql/init/Create.1.sql",
"chars": 174,
"preview": "\nPRAGMA user_version = 1;\n\nCREATE TABLE IF NOT EXISTS `accounts`(\n id NUMERIC(19,0) PRIMARY KEY,\n screen_name VARCHAR("
},
{
"path": "sql/init/Create.2.sql",
"chars": 312,
"preview": "\nPRAGMA user_version = 2;\n\nCREATE TABLE IF NOT EXISTS `snippets`(\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n key VARCHAR("
},
{
"path": "sql/init/Create.3.sql",
"chars": 167,
"preview": "PRAGMA user_version = 3;\n\nALTER TABLE `accounts`\nADD migrated INT DEFAULT 0;\n\nCREATE TABLE IF NOT EXISTS `info`(\n key V"
},
{
"path": "sql/init/Create.4.sql",
"chars": 240,
"preview": "PRAGMA user_version = 4;\n\nALTER TABLE `accounts`\nADD token VARCHAR(100);\n\nALTER TABLE `accounts`\nADD token_secret VARCHA"
},
{
"path": "src/Account.vala",
"chars": 27646,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/Cawbird.vala",
"chars": 24288,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/CbAvatarCache.c",
"chars": 6810,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2016 Timm Bäder (C"
},
{
"path": "src/CbAvatarCache.h",
"chars": 3060,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n* Copyright (C) 2016 Timm Bäder (Co"
},
{
"path": "src/CbBundle.c",
"chars": 7300,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbBundle.h",
"chars": 2158,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbBundleHistory.c",
"chars": 4028,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbBundleHistory.h",
"chars": 2111,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbDeltaUpdater.c",
"chars": 3160,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbDeltaUpdater.h",
"chars": 1916,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbEmojiChooser.c",
"chars": 21869,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbEmojiChooser.h",
"chars": 1842,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbFilter.c",
"chars": 2648,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbFilter.h",
"chars": 1559,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbGtkCompat.h",
"chars": 2088,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbMedia.c",
"chars": 6679,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2016 Timm Bäder (C"
},
{
"path": "src/CbMedia.h",
"chars": 2510,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2016 Timm Bäder (C"
},
{
"path": "src/CbMediaDownloader.c",
"chars": 19308,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2016 Timm Bäder (C"
},
{
"path": "src/CbMediaDownloader.h",
"chars": 3416,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2016 Timm Bäder (C"
},
{
"path": "src/CbMediaImageWidget.c",
"chars": 6277,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbMediaImageWidget.h",
"chars": 1550,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbMediaVideoWidget.c",
"chars": 11625,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbMediaVideoWidget.h",
"chars": 1746,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbMessageReceiver.c",
"chars": 1437,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbMessageReceiver.h",
"chars": 1586,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbSnippetManager.c",
"chars": 5751,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbSnippetManager.h",
"chars": 2946,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbSurfaceProgress.c",
"chars": 5121,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbSurfaceProgress.h",
"chars": 1719,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbTextTransform.c",
"chars": 10539,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2016 Timm Bäder (C"
},
{
"path": "src/CbTextTransform.h",
"chars": 1719,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbTweet.c",
"chars": 17242,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2016 Timm Bäder (C"
},
{
"path": "src/CbTweet.h",
"chars": 5692,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2016 Timm Bäder (C"
},
{
"path": "src/CbTweetModel.c",
"chars": 19042,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbTweetModel.h",
"chars": 4055,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbTwitterItem.c",
"chars": 2648,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbTwitterItem.h",
"chars": 1966,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbTypes.c",
"chars": 22371,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2016 Timm Bäder (C"
},
{
"path": "src/CbTypes.h",
"chars": 3555,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2016 Timm Bäder (C"
},
{
"path": "src/CbUserCompletionModel.c",
"chars": 5900,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbUserCompletionModel.h",
"chars": 2010,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbUserCounter.c",
"chars": 11085,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbUserCounter.h",
"chars": 2778,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbUserStream.c",
"chars": 26077,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbUserStream.h",
"chars": 3182,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbUtils.c",
"chars": 17195,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/CbUtils.h",
"chars": 3504,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/ComposedTweet.vala",
"chars": 2818,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2020 IBBoard\n *\n *"
},
{
"path": "src/DMManager.vala",
"chars": 8636,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/DMPage.vala",
"chars": 31405,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/DMThreadsPage.vala",
"chars": 10535,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/DefaultTimeline.vala",
"chars": 14425,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/FavoritesTimeline.vala",
"chars": 3503,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/FilterPage.vala",
"chars": 9102,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/HomeTimeline.vala",
"chars": 6638,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/IPage.vala",
"chars": 1325,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/ListStatusesPage.vala",
"chars": 14522,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/ListsPage.vala",
"chars": 4686,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/MainWidget.vala",
"chars": 7179,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/MainWindow.vala",
"chars": 18750,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/MediaUpload.vala",
"chars": 4266,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2020 IBBoard\n *\n *"
},
{
"path": "src/MentionsTimeline.vala",
"chars": 4700,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/NotificationManager.vala",
"chars": 2203,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/OAuthProxyCallWithBody.vala",
"chars": 1312,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/OAuthProxyCallWithQueryString.vala",
"chars": 1594,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/ProfilePage.vala",
"chars": 39254,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/SearchPage.vala",
"chars": 17395,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/Settings.vala",
"chars": 6263,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/TweetInfoPage.vala",
"chars": 40193,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/Twitter.vala",
"chars": 12999,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/UserEventReceiver.vala",
"chars": 5523,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/async/Collect.vala",
"chars": 1603,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/async/CollectById.vala",
"chars": 1886,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2020 IBBoard\n *\n *"
},
{
"path": "src/cawbird.vapi",
"chars": 20371,
"preview": "/* cawbird.vapi generated by valac 0.38.7, do not modify. */\n\nnamespace TweetUtils {\n\t[CCode (cheader_filename = \"cawbir"
},
{
"path": "src/libtl/data.h",
"chars": 26800,
"preview": "/* This file is part of libtweetlength\n * Copyright (C) 2017 Timm Bäder, 2020 IBBoard\n *\n * libtweetlength is free so"
},
{
"path": "src/libtl/libtweetlength.c",
"chars": 54393,
"preview": "/* This file is part of libtweetlength\n * Copyright (C) 2017 Timm Bäder\n *\n * libtweetlength is free software: you ca"
},
{
"path": "src/libtl/libtweetlength.h",
"chars": 2791,
"preview": "/* This file is part of libtweetlength\n * Copyright (C) 2017 Timm Bäder\n *\n * libtweetlength is free software: you ca"
},
{
"path": "src/list/AddListEntry.vala",
"chars": 1306,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/list/DMListEntry.vala",
"chars": 9511,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/list/DMThreadEntry.vala",
"chars": 2394,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/list/FavImageRow.vala",
"chars": 5021,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/list/FilterListEntry.vala",
"chars": 2688,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/list/ListListEntry.vala",
"chars": 5977,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/list/NewListEntry.vala",
"chars": 3762,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/list/SnippetListEntry.vala",
"chars": 2132,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/list/StartConversationEntry.vala",
"chars": 7505,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/list/TweetListEntry.vala",
"chars": 36112,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/list/UserFilterEntry.vala",
"chars": 3130,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/list/UserListEntry.vala",
"chars": 5595,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/main.vala",
"chars": 1648,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/model/DMThreadsModel.vala",
"chars": 4784,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/sql/BaseStatement.vala",
"chars": 2527,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2020 IBBoard\n *\n *"
},
{
"path": "src/sql/Database.vala",
"chars": 3572,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/sql/DeleteStatement.vala",
"chars": 2039,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2020 IBBoard\n *\n *"
},
{
"path": "src/sql/InsertStatement.vala",
"chars": 3370,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/sql/SelectStatement.vala",
"chars": 3081,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/sql/UpdateStatement.vala",
"chars": 2994,
"preview": "\n/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder ("
},
{
"path": "src/util/Benchmark.vala",
"chars": 1249,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2016 Timm Bäder (C"
},
{
"path": "src/util/Dirs.vala",
"chars": 2127,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/util/ListUtils.vala",
"chars": 1541,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2020 IBBoard\n *\n *"
},
{
"path": "src/util/TweetUtils.vala",
"chars": 41351,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/util/UserCompletion.vala",
"chars": 1909,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/util/UserUtils.vala",
"chars": 9499,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/util/Utils.vala",
"chars": 25784,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/widgets/AccountCreateWidget.vala",
"chars": 7134,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/widgets/AddImageButton.vala",
"chars": 6437,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/widgets/AspectImage.vala",
"chars": 3980,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/widgets/AvatarBannerWidget.vala",
"chars": 5205,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/widgets/AvatarWidget.vala",
"chars": 8403,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/widgets/BadgeRadioButton.vala",
"chars": 2450,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/widgets/CompletionTextView.vala",
"chars": 17423,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/widgets/ComposeImageManager.vala",
"chars": 15426,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/widgets/CropWidget.vala",
"chars": 13087,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/widgets/DMPlaceholderBox.vala",
"chars": 2044,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/widgets/DoubleTapButton.vala",
"chars": 1066,
"preview": "\n/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder ("
},
{
"path": "src/widgets/FavImageView.vala",
"chars": 7692,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2017 Timm Bäder (C"
},
{
"path": "src/widgets/FollowButton.vala",
"chars": 2564,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/widgets/ImpostorWidget.vala",
"chars": 1709,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/widgets/LazyMenuButton.vala",
"chars": 1048,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
},
{
"path": "src/widgets/ListBox.vala",
"chars": 3957,
"preview": "/* This file is part of Cawbird, a Gtk+ linux Twitter client forked from Corebird.\n * Copyright (C) 2013 Timm Bäder (C"
}
]
// ... and 65 more files (download for full content)
About this extraction
This page contains the full source code of the IBBoard/cawbird GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 265 files (2.8 MB), approximately 747.9k tokens, and a symbol index with 407 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.