# Code Property Graph
[![Actions Status](https://github.com/Fraunhofer-AISEC/cpg/workflows/build/badge.svg)](https://github.com/Fraunhofer-AISEC/cpg/actions)
 [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=Fraunhofer-AISEC_cpg&metric=alert_status)](https://sonarcloud.io/dashboard?id=Fraunhofer-AISEC_cpg) [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=Fraunhofer-AISEC_cpg&metric=security_rating)](https://sonarcloud.io/dashboard?id=Fraunhofer-AISEC_cpg) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=Fraunhofer-AISEC_cpg&metric=coverage)](https://sonarcloud.io/dashboard?id=Fraunhofer-AISEC_cpg) [![](https://jitpack.io/v/Fraunhofer-AISEC/cpg.svg)](https://jitpack.io/#Fraunhofer-AISEC/cpg)

A simple library to extract a *code property graph* out of source code. It has support for multiple passes that can extend the analysis after the graph is constructed. It currently supports C/C++ (C17), Java (Java 13) and has experimental support for Golang, Python and TypeScript. Furthermore, it has support for the [LLVM IR](http://llvm.org/docs/LangRef.html) and thus, theoretically support for all languages that compile using LLVM.

## What is this?

A code property graph (CPG) is a representation of source code in form of a labelled directed multi-graph. Think of it as directed a graph where each node and edge is assigned a (possibly empty) set of key-value pairs (_properties_). This representation is supported by a range of graph databases such as Neptune, Cosmos, Neo4j, Titan, and Apache Tinkergraph and can be used to store source code of a program in a searchable data structure. Thus, the code property graph allows to use existing graph query languages such as Cypher, NQL, SQL, or Gremlin in order to either manually navigate through interesting parts of the source code or to automatically find "interesting" patterns.

This library uses [Eclipse CDT](https://www.eclipse.org/cdt/) for parsing C/C++ source code [JavaParser](https://javaparser.org/) for parsing Java. In contrast to compiler AST generators, both are "forgiving" parsers that can cope with incomplete or even semantically incorrect source code. That makes it possible to analyze source code even without being able to compile it (due to missing dependencies or minor syntax errors). Furthermore, it uses [LLVM](https://llvm.org) through the [javacpp](https://github.com/bytedeco/javacpp) project to parse LLVM IR. Note that the LLVM IR parser is *not* forgiving, i.e., the LLVM IR code needs to be at least considered valid by LLVM. The necessary native libraries are shipped by the javacpp project for most platforms.

## Specifications

In order to improve some formal aspects of our library, we created several specifications of our core concepts. Currently, the following specifications exist:
* [Dataflow Graph](https://fraunhofer-aisec.github.io/cpg/CPG/specs/dfg/)
* [Evaluation Order Graph](https://fraunhofer-aisec.github.io/cpg/CPG/specs/eog/)
* [Graph Model in neo4j](https://fraunhofer-aisec.github.io/cpg/CPG/specs/graph/)
* [Language and Language Frontend](https://fraunhofer-aisec.github.io/cpg/CPG/impl/language/)

We aim to provide more specifications over time.

## Usage

To build the project from source, you have to generate a `gradle.properties` file locally.
This file also enables and disables the supported programming languages.
We provide a sample file [here](./gradle.properties.example) - simply copy it to `gradle.properties` in the directory of the cpg-project.
Instead of manually generating or editing the `gradle.properties` file, you can also use the `configure_frontends.sh` script, which edits the properties setting the supported programming languages for you.

### For Visualization Purposes

In order to get familiar with the graph itself, you can use the subproject [cpg-neo4j](https://github.com/Fraunhofer-AISEC/cpg/tree/master/cpg-neo4j). It uses this library to generate the CPG for a set of user-provided code files. The graph is then persisted to a [Neo4j](https://neo4j.com/) graph database. The advantage this has for the user, is that Neo4j's visualization software [Neo4j Browser](https://neo4j.com/developer/neo4j-browser/) can be used to graphically look at the CPG nodes and edges, instead of their Java representations.

### As Library

The most recent version is being published to Maven central and can be used as a simple dependency, either using Maven or Gradle.

```kotlin
dependencies {
    val cpgVersion = "8.0.0"

    // if you want to include all published cpg modules
    implementation("de.fraunhofer.aisec", "cpg", cpgVersion)

    // if you only want to use some of the cpg modules
    // use the 'cpg-core' module
    // and then add the needed extra modules, such as Go and Python
    implementation("de.fraunhofer.aisec", "cpg-core", cpgVersion)
    implementation("de.fraunhofer.aisec", "cpg-language-go", cpgVersion)
    implementation("de.fraunhofer.aisec", "cpg-language-python", cpgVersion)
}
```

There are some extra steps necessary for the `cpg-language-cxx` module. Since Eclipse CDT is not published on maven central, it is necessary to add a repository with a custom layout to find the released CDT files. For example, using Gradle's Kotlin syntax:
```kotlin
repositories {
    // This is only needed for the C++ language frontend
    ivy {
        setUrl("https://download.eclipse.org/tools/cdt/releases/")
        metadataSources {
            artifact()
        }

        patternLayout {
            artifact("[organisation].[module]_[revision].[ext]")
        }
    }
}
```

Beware, that the `cpg` module includes all optional features and might potentially be HUGE (especially because of the LLVM support). If you do not need LLVM, we suggest just using the `cpg-core` module with the needed extra modules like `cpg-language-go`. In the future we are working on extracting more optional modules into separate modules.

#### Development Builds

A published artifact of every commit can be requested through [JitPack](https://jitpack.io/#Fraunhofer-AISEC/cpg). This is especially useful, if your external project makes use of a specific feature that is not yet merged in yet or not published as a version yet. Please follow the instructions on the JitPack page. Please be aware, that similar to release builds, the CDT repository needs to be added as well (see above).

### On Command Line

The library can be used on the command line using the `cpg-console` subproject. Please refer to the [README.md](./cpg-console/README.md) of the `cpg-console` as well as our small [tutorial](./tutorial.md) for further details.

### Configuration

The behavior of the library can be configured in several ways. Most of this is done through the `TranslationConfiguration`
and the `InferenceConfiguration`.

#### TranslationConfiguration

The `TranslationConfiguration` configures various aspects of the translation. E.g., it determines which languages/language
frontends and passes will be used, which information should be inferred, which files will be included, among others. The
configuration is set through a builder pattern.

#### InferenceConfiguration

The class `InferenceConfiguration` can be used to affect the behavior or the passes if they identify missing nodes.
Currently, there are three flags which can be enabled:

* `guessCastExpression` enables guessing if a CPP expression is a cast or a call expression if it is not clear.
* `inferRecords` enables the inference of missing record declarations (i.e., classes and structs)
* `inferDfgForUnresolvedSymbols` adds DFG edges to method calls represent all potential data flows if the called function
  is not present in the source code under analysis.

Only `inferDfgForUnresolvedSymbols` is turned on by default.

The configuration can be made through a builder pattern and is set in the `TranslationConfiguration` as follows:
```kt
val inferenceConfig = InferenceConfiguration
    .builder()
    .guessCastExpression(true)
    .inferRecords(true)
    .inferDfgForUnresolvedSymbols(true)
    .build()

val translationConfig = TranslationConfiguration
    .builder()
    .inferenceConfiguration(inferenceConfig)
    .build()
```

## Development Setup

### Experimental Languages

Some languages, such as Golang are experimental and depend on other native libraries. Therefore, they are not included in the `cpg-core` module but have separate gradle submodules.
To include the desired submodules simply toggle them on in your local `gradle.properties` file by setting the value of the properties to `true` e.g., (`enableGoFrontend=true`).
We provide a sample file with all languages switched on [here](./gradle.properties.example).
Instead of manually editing the `gradle.properties` file, you can also use the `configure_frontends.sh` script, which edits the properties for you.

#### Golang

In the case of Golang, the necessary native code can be found in the `src/main/golang` folder of the `cpg-language-go` submodule. Gradle should automatically store the finished library in the `src/main/golang` folder. This currently only works for Linux and macOS.

#### Python

You need to install [jep](https://github.com/ninia/jep/). This can either be system-wide or in a virtual environment. Your jep version has to match the version used by the CPG (see [version catalog](./gradle/libs.versions.toml)).

Currently, only Python 3.{9,10,11,12,13} is supported.

##### System Wide

Follow the instructions at https://github.com/ninia/jep/wiki/Getting-Started#installing-jep.

##### Virtual Env

- `python3 -m venv ~/.virtualenvs/cpg`
- `source ~/.virtualenvs/cpg/bin/activate`
- `pip3 install jep`

Through the `JepSingleton`, the CPG library will look for well known paths on Linux and OS X. `JepSingleton` will prefer a virtualenv with the name `cpg`, this can be adjusted with the environment variable `CPG_PYTHON_VIRTUALENV`.

#### TypeScript

For parsing TypeScript, the necessary NodeJS-based code can be found in the `src/main/nodejs` directory of the `cpg-language-typescript` submodule. Gradle should build the script automatically, provided NodeJS (>=16) is installed. The bundles script will be placed inside the jar's resources and should work out of the box.

### Code Style

We use [Google Java Style](https://github.com/google/google-java-format) as a formatting. Please install the appropriate plugin for your IDE, such as the [google-java-format IntelliJ plugin](https://plugins.jetbrains.com/plugin/8527-google-java-format) or [google-java-format Eclipse plugin](https://github.com/google/google-java-format/releases/download/google-java-format-1.6/google-java-format-eclipse-plugin_1.6.0.jar).

### Integration into IntelliJ

Straightforward, however three things are recommended

* Enable gradle "auto-import"
* Enable google-java-format
* Hook gradle spotlessApply into "before build" (might be obsolete with IDEA 2019.1)

### Git Hooks

You can use the hook in `style/pre-commit` to check for formatting errors:
```
cp style/pre-commit .git/hooks
```

## Contributors

The following authors have contributed to this project (in alphabetical order):
* [fwendland](https://github.com/fwendland)
* [JulianSchuette](https://github.com/JulianSchuette)
* [konradweiss](https://github.com/konradweiss)
* [KuechA](https://github.com/KuechA)
* [Masrepus](https://github.com/Masrepus)
* [maximiliankaul](https://github.com/maximiliankaul)
* [maximilian-galanis](https://github.com/maximilian-galanis)
* [obraunsdorf](https://github.com/obraunsdorf)
* [oxisto](https://github.com/oxisto)
* [peckto](https://github.com/peckto)
* [titze](https://github.com/titze)
* [vfsrfs](https://github.com/vfsrfs)

## Contributing

Before accepting external contributions, you need to sign our [CLA](https://cla-assistant.io/Fraunhofer-AISEC/cpg). Our CLA assistent will check, whether you already signed the CLA when you open your first pull request.

## Further reading

You can find a complete list of papers [here](https://fraunhofer-aisec.github.io/cpg/#publications)

A quick write-up of our CPG has been published on arXiv:

[1] Konrad Weiss, Christian Banse. A Language-Independent Analysis Platform for Source Code. https://arxiv.org/abs/2203.08424

A preliminary version of this cpg has been used to analyze ARM binaries of iOS apps:

[2] Julian Schütte, Dennis Titze. _liOS: Lifting iOS Apps for Fun and Profit._ Proceedings of the ESORICS International Workshop on Secure Internet of Things (SIoT), Luxembourg, 2019. https://arxiv.org/abs/2003.12901

An initial publication on the concept of using code property graphs for static analysis:

[3] Yamaguchi et al. - Modeling and Discovering Vulnerabilities with Code Property Graphs. https://www.sec.cs.tu-bs.de/pubs/2014-ieeesp.pdf

[4] is an unrelated, yet similar project by the authors of the above publication, that is used by the open source software Joern [5] for analysing C/C++ code. While [4] is a specification and implementation of the data structure, this project here includes various _Language frontends_ (currently C/C++ and Java, Python to com) and allows creating custom graphs by configuring _Passes_ which extend the graph as necessary for a specific analysis:

[4] https://github.com/ShiftLeftSecurity/codepropertygraph

[5] https://github.com/ShiftLeftSecurity/joern/

Additional extensions of the CPG to support further use-cases:

[6] Christian Banse, Immanuel Kunz, Angelika Schneider and Konrad Weiss. Cloud Property Graph: Connecting Cloud Security Assessments with Static Code Analysis.  IEEE CLOUD 2021. https://doi.org/10.1109/CLOUD53861.2021.00014

[7] Alexander Küchler, Christian Banse. Representing LLVM-IR in a Code Property Graph. 25th Information Security Conference (ISC). Bali, Indonesia. 2022

[8] Maximilian Kaul, Alexander Küchler, Christian Banse. A Uniform Representation of Classical and Quantum Source Code for Static Code Analysis. IEEE International Conference on Quantum Computing and Engineering (QCE). Bellevue, WA, USA. 2023


![](https://user-images.githubusercontent.com/7698209/33198075-ef8f2230-d123-11e7-85a3-4cb9b22f877d.png)
[![](https://img.shields.io/maven-central/v/io.github.cymchad/BaseRecyclerViewAdapterHelper4)](https://repo.maven.apache.org/maven2/io/github/cymchad/BaseRecyclerViewAdapterHelper4/) [![API](https://img.shields.io/badge/API-16%2B-brightgreen.svg?style=flat)](https://android-arsenal.com/api?level=16) [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-BaseRecyclerViewAdapterHelper-green.svg?style=true)](https://android-arsenal.com/details/1/3644) [![CircleCI](https://circleci.com/gh/CymChad/BaseRecyclerViewAdapterHelper/tree/master.svg?style=svg)](https://circleci.com/gh/CymChad/BaseRecyclerViewAdapterHelper/tree/master) [![](https://img.shields.io/badge/%E4%BD%9C%E8%80%85-%E9%99%88%E5%AE%87%E6%98%8E-7AD6FD.svg)](https://mp.weixin.qq.com/s/5UlMx9HDgEcvxJb4w5-gBA) [![](https://img.shields.io/badge/%E4%BD%9C%E8%80%85-limuyang2-7AD6FD)](https://github.com/limuyang2)
# BRVAH
http://www.recyclerview.org/

Powerful and flexible RecyclerView Adapter,
Please feel free to use this. (Welcome to **Star** and **Fork**)

强大而灵活的RecyclerView Adapter（欢迎 **Star** 和 **Fork**）

新版4.x.x已发布，完美兼容`ConcatAdapter`，解决了许多遗留问题，拆分了功能模块，BaseAdapter更加简洁干净。“多类型布局”更加灵活。向上、向下加载得到极大加强。
v4版本已经上传 maven 中央仓库，不需要再引入三方仓库配置了。欢迎尝试。
```
implementation "io.github.cymchad:BaseRecyclerViewAdapterHelper4:4.1.4"
```

Of course, you can continue to use the [2.x](https://github.com/CymChad/BaseRecyclerViewAdapterHelper/tree/2.x) version.

当然，你也可以继续使用[2.x](https://github.com/CymChad/BaseRecyclerViewAdapterHelper/tree/2.x) 版本、[3.x](https://github.com/CymChad/BaseRecyclerViewAdapterHelper/blob/3.x/readme/0-BaseRecyclerViewAdapterHelper.md)版本。

# Document
- English Writing ...
- [3.0版本 中文](https://github.com/CymChad/BaseRecyclerViewAdapterHelper/blob/3.x/readme/0-BaseRecyclerViewAdapterHelper.md)
- [4.0版本 中文](https://github.com/CymChad/BaseRecyclerViewAdapterHelper/wiki)

(由于各位项目成员工作较为繁忙，请各位同学谅解)

## v4 版本 Demo
[wiki](https://github.com/CymChad/BaseRecyclerViewAdapterHelper/wiki)

# proguard-rules.pro
> 此资源库自带混淆规则，并且会自动导入，正常情况下无需手动导入。

> The library comes with `proguard-rules.pro` rules and is automatically imported. Normally no manual import is required.
> You can also go here to view [proguard-rules](https://github.com/CymChad/BaseRecyclerViewAdapterHelper/blob/master/library/proguard-rules.pro)

# Thanks
[JoanZapata / base-adapter-helper](https://github.com/JoanZapata/base-adapter-helper)

# [License](https://github.com/CymChad/BaseRecyclerViewAdapterHelper/blob/master/LICENSE)


# Ground for Android
[![cloud build status](https://storage.googleapis.com/gradle_cache_bucket/status.svg)](https://console.cloud.google.com/cloud-build/dashboard?project=ground-android-gcb)
[![codecov.io](https://codecov.io/github/google/ground-android/branch/master/graph/badge.svg)](https://codecov.io/github/google/ground-android)
[![Open Source Helpers](https://www.codetriage.com/google/ground-android/badges/users.svg)](https://www.codetriage.com/google/ground-android)

Ground is an open-source, map-first data collection and analysis platform built
to seamlessly connect the offline world with cloud-based storage and
computation. The platform consists of a web app for data management and an
Android app for offline data collection. Our goal is to provide a "just right"
data collection solution that meets the needs of community organizers,
conservationists, humanitarian workers, and researchers addressing some of
today's most pressing issues.

**Note:** Ground is not an officially supported Google product, and is developed
on a best-effort basis.

You can learn more about Ground on the [project
website](https://google.github.io/ground-platform).

## Contributing

We'd love to accept your patches and contributions to this project. For more
information, including details on the required Contributor License Agreement
(CLA), code reviews, and environment setup, see
[Contributing to Ground for Android](CONTRIBUTING.md).


[![Build Status](https://travis-ci.org/adrcotfas/Goodtime.svg?branch=master)](https://travis-ci.org/adrcotfas/Goodtime) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/goodtime/localized.svg)](https://crowdin.com/project/goodtime)

# Goodtime
[](https://play.google.com/store/apps/details?id=com.apps.adrcotfas.goodtime&utm_source=global_co&utm_medium=prtnr&utm_content=Mar2515&utm_campaign=PartBadge&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1)
[](https://f-droid.org/packages/com.apps.adrcotfas.goodtime)

A minimalist but powerful productivity timer designed to keep you focused and free of distractions.
Alternate between focused work sessions and short breaks, all handled by the app.
Get rid of procrastination and improve your time management!

⏳ split your work into focused sessions and then reward yourself with a break
☕ after multiple work sessions, take a longer break

## Features
- No ads
- No tracking or personal data collection
- Free & Open Source
- Lightweight: ~2 MB download size
- Battery friendly
- Configurable timer
- Pause, skip or add 60 seconds
- Long breaks after a number of completed work sessions
- Detailed statistics
- AMOLED-friendly user interface
- Immersive fullscreen mode
- Keep the screen on
- Custom notification sounds
- Auto start work or break without user interaction
- Disable sound and Wi-Fi connection during the work sessions
- Colored labels
- Timer styles
- Daily reminder
- Manually add sessions
- Edit completed sessions
- Backup export and import
- Export statistics to CSV
- Screensaver mode
- Themes
- Separate notification sound for work and break
- Insistent notifications

## Translations
You can help translate or improve existing translations at [Crowdin](https://crowdin.com/project/goodtime). Thank you!

## Trouble with Goodtime getting killed by Android?
Different phone [OEMs](https://en.wikipedia.org/wiki/Original_equipment_manufacturer) (phone vendors) have an aggressive take towards apps that rely on background work and alarms to save some battery life.
It is recommended that you disable the battery optimization for this app in order to get accurate alarms.
In the worst case, if you still have issues, try to keep the phone plugged in and/or the screen on while working.

Read more about this topic on [www.dontkillmyapp.com](https://dontkillmyapp.com/)

## Suggestions, questions, contact
For any suggestions or questions, please contact me and I'll be glad to help!

You may also browse the [issues](https://github.com/adrcotfas/Goodtime/issues) to see if your question or request already exists and open a new issue if necessary.

## Licence
Goodtime is free and open source software, [licensed](https://github.com/adrcotfas/Goodtime/blob/master/LICENCE.md) under the Apache License, Version 2.0.
Copyright 2016-2019 Adrian Cotfas.


# Jicofo

JItsi COnference FOcus is a signaling server, one of the backend components in the [Jitsi Meet] stack.

[Jitsi Meet]: https://github.com/jitsi/jitsi-meet

## Overview

Jitsi Meet conferences are associated with an XMPP
[Multi-User Chat (MUC) room](https://xmpp.org/extensions/xep-0045.html). The MUC functionality is provided by the
XMPP server (prosody).

Jicofo joins the conference MUC and is then responsible for initiating a
[Jingle](https://xmpp.org/extensions/xep-0166.html) session with each participant (in this sense it is the "focus" of the
conference, which is where its name comes from). While Jicofo manages and terminates Jingle sessions, it does not
process any of the media (audio/video). Instead, it uses one or more
[Jitsi Videobridge](github.com/jitsi/jitsi-videobridge/) instances.

Jicofo is responsible for selecting a Jitsi Videobridge for each participant, and manages the set of videobridges for
the conference with the COLIBRI protocol (colibri version 2 is now used, the format in XEP-0340 is now deprecated).

In general the conference participants and videobridge instances are accessed through different XMPP connections --
the configured Client and Service connections, respectively, though they may coincide.

![Connection between Jicofo and the other components in the Jitsi Meet stack.](https://github.com/jitsi/jicofo/blob/master/doc/diagram.png?raw=true)

# Configuration
Jicofo takes its configuration from a [hocon](https://github.com/lightbend/config/blob/main/HOCON.md) config file,
usually installed in `/etc/jitsi/jicofo/jicofo.conf`. See the
[reference.conf](https://github.com/jitsi/jicofo/blob/master/jicofo-selector/src/main/resources/reference.conf) file
for the available options.

# Installation
## Debian

The recommended way to install Jicofo and Jitsi Meet is to follow the
[Quick Install Guide](https://github.com/jitsi/jitsi-meet/blob/master/doc/quick-install.md) for debian-based systems.

### Binaries

You can download Debian/Ubuntu binaries here:
* [stable](https://download.jitsi.org/stable/) ([instructions](https://jitsi.org/downloads/ubuntu-debian-installations-instructions/))
* [testing](https://download.jitsi.org/testing/) ([instructions](https://jitsi.org/downloads/ubuntu-debian-installations-instructions-for-testing/))
* [nightly](https://download.jitsi.org/unstable/) ([instructions](https://jitsi.org/downloads/ubuntu-debian-installations-instructions-nightly/))

## Docker
Jicofo is available as a docker image as part of [docker-jitsi-meet](https://github.com/jitsi/docker-jitsi-meet).

## Manual
This section is only required for a manual setup, not necessary when using Quick Install or other methods.

### Prosody configuration

Jicofo needs privileges to create Multi-User Chat rooms. To grant these privileges we create an account for it and add
it to the global `admins` list. We create a new virtual host, because the one used by clients only supports anonymous
authentication. We add this to Prosody's config file (`/etc/prosody/prosody.cfg.lua` by default):
```
admins = { focus@auth.jitsi.example.com }
VirtualHost "auth.jitsi.example.com"
    authentication = "internal_hashed"
```
Then restart Prosody and create the user account:
```
sudo prosodyctl restart
sudo prosodyctl register focus auth.jitsi.example.com focuspassword
```

### Building Jicofo
Build using maven with:
```commandline
mvn install
```

This will create a package in `jicofo/target/jicofo-1.1-SNAPSHOT-archive.zip`
### Running Jicofo
Extract the distribution package and run with `jicofo.sh`.

### Certificates
Jicofo uses an XMPP user connection (on port 5222 by default), and since the
upgrade to smack4 it verifies the server's certificate. In a default
installation the debian installation scripts take care of generating a
self-signed certificate and adding it to the keystore.

For situations in which the certificate is not trusted you can add it to the
store by:

#### On Linux
```
sudo cp cert.pem /usr/local/share/ca-certificates/
sudo update-ca-certificates
```

#### On MacOS X
On Mac java uses its own keystore, so adding the certificate to the system one
does not work. Add it to the java keystore with:
```
sudo keytool -importcert -file cert.pem -keystore /Library/Java//JavaVirtualMachines/jdk1.8.0_25.jdk/Contents/Home/jre/lib/security/cacerts
```

Note that if the XMPP server you are connecting to is a prosody instance
configured with the jitsi-meet scripts, then you can find the certificate in:
```
/var/lib/prosody/$JICOFO_AUTH_DOMAIN.crt
```


![Checkout Android Logo][header.image]

[![Maven Central][shield.mavenCentral.image]][shield.mavenCentral.link]
[![Build status][shield.buildStatus.image]][shield.buildStatus.link]
[![License][shield.license.image]][shield.license.link]

# Adyen Android

Adyen Android allows you to accept in-app payments by providing you with the building blocks you need to create a checkout experience.

For an overview of how you can integrate with Adyen on Android check out the [documentation][docs.android].

![DropIn Preview][header.preview]

## Prerequisites

* [Adyen test account][adyen.testAccount]
* [API key][docs.apiKey]
* [Client key][docs.clientKey]

## Installation

There are two main integration types: [Drop-in][docs.dropIn] and [Components][docs.components].
Import the corresponding module in your `build.gradle` file.

### With Jetpack Compose

For Drop-in:
```groovy
implementation "com.adyen.checkout:drop-in-compose:5.5.0"
```
For the Credit Card component:
```groovy
implementation "com.adyen.checkout:card:5.5.0"
implementation "com.adyen.checkout:components-compose:5.5.0"
```

### Without Jetpack Compose

For Drop-in:
```groovy
implementation "com.adyen.checkout:drop-in:5.5.0"
```
For the Credit Card component:
```groovy
implementation "com.adyen.checkout:card:5.5.0"
```

The library is available on [Maven Central][mavenRepo].

## UI Customization

[See the UI Customization Guide for more.](docs/UI_CUSTOMIZATION.md)

## Migrate from v4

If you are upgrading from 4.x.x to a current release, check out our [migration guide][migration.guide].

## ProGuard

If you use ProGuard or R8, you do not need to manually add any rules, as they are automatically embedded in the artifacts.
Please let us know if you find any issues.

## Development

For development and testing purposes the project is accompanied by a test app. See [here](example-app/README.md) how to set it up and run it.

## Support

If you have a feature request, or spotted a bug or a technical problem, [create an issue here][github.newIssue].

For other questions, [contact our support team][adyen.support].

## Analytics and data tracking

Starting [5.0.0][analytics.firstVersion] the Drop-in and Components integrations contain analytics and tracking features that are turned on by default. Find out more about [what we track and how you can control it][docs.analytics].

## Contributing

We merge every pull request into the `develop` branch. We aim to keep `develop` in good shape, which allows us to release a new version whenever we need to.

Have a look at our [contributing guidelines][contributing.guidelines] to find out how to raise a pull request.

## See also

* [Android API documentation][dokka]

* [Adyen Checkout Documentation][docs.checkout]

* [Adyen API Explorer][docs.apiExplorer]

## License

This repository is available under the [MIT license](LICENSE).

[header.image]: https://user-images.githubusercontent.com/9079915/198013698-139bf6f1-a15a-447d-8eed-97ce1354b43f.png
[shield.mavenCentral.image]: https://img.shields.io/maven-central/v/com.adyen.checkout/drop-in
[shield.mavenCentral.link]: https://mvnrepository.com/artifact/com.adyen.checkout
[shield.buildStatus.image]: https://github.com/Adyen/adyen-android/actions/workflows/check_release.yml/badge.svg
[shield.buildStatus.link]: https://github.com/Adyen/adyen-android/actions
[shield.license.image]: https://img.shields.io/github/license/Adyen/adyen-android
[shield.license.link]: LICENSE
[docs.android]: https://docs.adyen.com/online-payments/build-your-integration/?platform=Android
[header.preview]: https://github.com/Adyen/adyen-android/assets/9079915/e6e18a07-b30f-41f0-b7ef-701b20e2e339
[adyen.testAccount]: https://www.adyen.com/signup
[docs.apiKey]: https://docs.adyen.com/development-resources/how-to-get-the-api-key
[docs.clientKey]: https://docs.adyen.com/development-resources/client-side-authentication#get-your-client-key
[docs.dropIn]: https://docs.adyen.com/online-payments/build-your-integration/?platform=Android&integration=Drop-in
[docs.components]: https://docs.adyen.com/online-payments/build-your-integration/?platform=Android&integration=Components
[mavenRepo]: https://repo1.maven.org/maven2/com/adyen/checkout/
[migration.guide]: https://docs.adyen.com/online-payments/build-your-integration/migrate-to-android-5-0-0
[github.newIssue]: https://github.com/Adyen/adyen-android/issues/new/choose
[adyen.support]: https://www.adyen.help/hc/en-us/requests/new
[analytics.firstVersion]: https://github.com/Adyen/adyen-android/releases/tag/5.0.0
[docs.analytics]: https://docs.adyen.com/online-payments/analytics-and-data-tracking
[contributing.guidelines]: https://github.com/Adyen/.github/blob/main/CONTRIBUTING.md
[dokka]: https://adyen.github.io/adyen-android/
[docs.checkout]: https://docs.adyen.com/online-payments/
[docs.apiExplorer]: https://docs.adyen.com/api-explorer/


# Codyze :mag_right: :rocket:

[![build](https://github.com/Fraunhofer-AISEC/codyze/actions/workflows/build.yml/badge.svg)](https://github.com/Fraunhofer-AISEC/codyze/actions/workflows/build.yml)
![GitHub last commit](https://img.shields.io/github/last-commit/Fraunhofer-AISEC/codyze)
[![codecov](https://codecov.io/gh/Fraunhofer-AISEC/codyze/branch/main/graph/badge.svg)](https://codecov.io/gh/Fraunhofer-AISEC/codyze)
![GitHub](https://img.shields.io/github/license/Fraunhofer-AISEC/codyze)
[![](https://jitpack.io/v/Fraunhofer-AISEC/codyze.svg)](https://jitpack.io/#Fraunhofer-AISEC/codyze)

> :warning: This version of Codyze is still under development.
> If you are looking for a _stable_ version, please use the [2.3.0](https://github.com/Fraunhofer-AISEC/codyze/releases/tag/v2.3.0) release.

Codyze is a static code analyzer that focuses on verifying security compliance in source code, i.e. by inferring the correct use of cryptographic libraries. It operates on code property graphs and is thus able to handle non-compiling or even incomplete code fragments.

## Build & Run Codyze
A Java SE 17 JDK is a prerequisite. We build and test using Eclipse Temurin but any distribution should work.

To build an executable version of Codyze, use the `installDist` task in the project's root:

```shell
$ ./gradlew :codyze-cli:installDist
```
This will provide you with an executable Codyze installation under `codyze-cli/build/install/codyze-cli`.

To run Codyze you can either run this executable or use the `run` task:
```shell
$ ./gradlew run
```
This will print the help message and return an error.

To actually run Codyze you must specify a subcommand:
```shell
$ ./gradlew run --args="--config=config.json runCoko cokoCpg"
```
This will run the `runCoko` subcommand with the `cokoCpg` backend using the demo config file [`./codyze-cli/config.json`](./codyze-cli/config.json).

For more information, please refer to the [documentation](https://www.codyze.io).

## Research & Student Work

If you are looking for an exciting thesis project or student job in the field of static analysis, we are happy to discuss possible topics. Please contact us at _codyze [at] aisec.fraunhofer.de_.

## Support

We will continue to maintain this project for the foreseeable future on a best-effort basis. That is, if you run into any bugs or find the documentation insufficient, we encourage you to open issues or pull requests. If you are interested in support and development for commercial use, please contact us.

## License

[Apache License 2.0](./LICENSE)


[![CircleCI](https://circleci.com/gh/kickstarter/android-oss.svg?style=svg)](https://circleci.com/gh/kickstarter/android-oss)
[![codecov](https://codecov.io/gh/kickstarter/android-oss/branch/master/graph/badge.svg?token=uYNatHIB8b)](https://codecov.io/gh/kickstarter/android-oss)
[![ktlint](https://img.shields.io/badge/code%20style-%E2%9D%A4-FF4081.svg)](https://ktlint.github.io/)

Welcome to Kickstarter's open source Android app! Come on in, take your shoes
off, stay a while—_explore_ how Kickstarter's native squad has built and
continues to build the app, _discover_ our implementation of [RxJava](https://github.com/ReactiveX/RxJava) in logic-
filled [view models](https://github.com/kickstarter/android-oss/tree/master/app/src/main/java/com/kickstarter/viewmodels),
and maybe even _create_ an issue or two.

We've also open sourced our iOS app, written in Swift:
[check it out here](https://github.com/kickstarter/ios-oss). Read more about our journey to open source [here](https://kickstarter.engineering/open-sourcing-our-android-and-ios-apps-6891be909fcd#.o1fe86s6w).

## Getting Started

_Follow these instructions to build and run the project with mock data.._

1. Clone this repository.
2. Download the appropriate [JDK](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)
for your system. We are currently on JDK 8.
3. [Install Android Studio](https://developer.android.com/sdk/index.html).
4. `cd` into the project repo and run `make bootstrap` to bootstrap your Android
   development environment. Keep an eye on the output to see if any manual steps
   are required.
5. Import the project. Open Android Studio, click `Open an existing Android
   Studio project` and select the project. Gradle will build the project.
6. Run the app. Click `Run > Run 'app'`. After the project builds you'll be
   prompted to build or launch an emulator.

## Documentation

While we're at it, why not share our docs? Check out the
[native docs](https://github.com/kickstarter/native-docs) we have written so far
for more documentation.

## Contributing

We intend for this project to be an educational resource: we are excited to
share our wins, mistakes, and methodology of Android development as we work
in the open. Our primary focus is to continue improving the app for our users in
line with our roadmap.

The best way to submit feedback and report bugs is to open a Github issue.
Please be sure to include your operating system, device, version number, and
steps to reproduce reported bugs. Keep in mind that all participants will be
expected to follow our code of conduct.

## Code of Conduct

We aim to share our knowledge and findings as we work daily to improve our
product, for our community, in a safe and open space. We work as we live, as
kind and considerate human beings who learn and grow from giving and receiving
positive, constructive feedback. We reserve the right to delete or ban any
behavior violating this base foundation of respect.

## Find this interesting?

We do too, and we’re [hiring](https://www.kickstarter.com/jobs?ref=gh_android_oss)!

## License

```
Copyright 2020 Kickstarter, PBC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```


# Sessionize/Droidcon Mobile Clients

## General Info

This project has a pair of native mobile applications backed by the Sessionize data api for use in events hosted by the Sessionize web application. These are specifically for Droidcon events, but can be forked and customized for anything run on Sessionize.

> ## Subscribe!
>
> We build solutions that get teams started smoothly with Kotlin Multiplatform and ensure their success in production. Join our community to learn how your peers are adopting KMM.
[Sign up here](https://touchlab.co/?s=shownewsletter)!

## Building

The apps need a Firebase account set up to run. You'll need to get the `google-services.json` and put it in `android/google-services.json` for Android, and
the `GoogleService-Info.plist` and put that in `ios/Droidcon/Droidcon/GoogleService-Info.plist` for iOS.

## Compose UI for both!

We're running a very early version of Compose UI for iOS as the iOS interface. It mostly shares the screen code with the Android app. While Native Compose UI is obviously experimental, it works surprisingly well.

[Check out the blog post](https://touchlab.co/droidcon-nyc-ios-app-with-compose/)

## Media

[Blog posts and videos ->](MEDIA.md)

## About

Sessionize/Droidcon brought to you by...

[![Touchlab Logo](tlsmall.png "Touchlab Logo")](https://touchlab.co)


# S1 Next

[![GitHub version](https://badge.fury.io/gh/ykrank%2FS1-Next.svg)](http://badge.fury.io/gh/ykrank%2FS1-Next)

This is the Android Client for [STAGE1](http://bbs.saraba1st.com/2b/forum.php).

## Download
[GooglePlay](https://play.google.com/store/apps/details?id=me.ykrank.s1next)
[CoolApk](https://www.coolapk.com/)search S1Next

## License

[Apache license 2.0](https://www.apache.org/licenses/LICENSE-2.0.html)

## Third-party Licenses

See [Licenses](app/src/main/assets/text/license)

## Alternatives

- [Stage1](https://play.google.com/store/apps/details?id=com.motion.stage1) – Android
- [Stage1st Go](https://play.google.com/store/apps/details?id=org.succlz123.s1go.app) – Android
- [S1 Pluto](https://itunes.apple.com/cn/app/s1-pluto/id889820003) – iOS
- [Stage1st Reader](https://itunes.apple.com/cn/app/stage1st-reader/id509916119) – iOS
- [S1 Nyan](https://www.windowsphone.com/zh-cn/store/app/s1-nyan/61790166-792c-493b-bcc2-a2f1506292f5) – WP


[![Travis CI](https://api.travis-ci.org/mixitconf/mixit.svg?branch=master)](https://travis-ci.org/mixitconf/mixit)

# MiXiT website

This project purpose is to power the MiXiT website.

## Software design

This project software design goal is to demonstrate what a functional web application
developed with Spring Boot 2, Spring WebFlux and Kotlin can look like:
 - Reactive and non-blocking
 - More functional style and less annotation based than typical Spring applications
 - Leverage Kotlin features like [Kotlin extensions](https://kotlinlang.org/docs/reference/extensions.html) and [reified type parameters](https://kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters) for cleaner code
 - Simple, fast to start, efficient request processing, low memory consumption
 - [Constructor based injection](http://olivergierke.de/2013/11/why-field-injection-is-evil/)
 - Immutable Pojos
 - Cloud Native

### Technologies used

 - Language: [Kotlin](https://kotlin.link/)
 - Framework: [Spring Boot 3.x](https://projects.spring.io/spring-boot/) with [Spring 5 Kotlin support](https://docs.spring.io/spring-framework/docs/5.0.x/spring-framework-reference/kotlin.html) and [Spring WebFlux functional](https://docs.spring.io/spring-framework/docs/5.0.x/spring-framework-reference/reactive-web.html)
 - Engine: [Netty](http://netty.io/) used for client and server
 - Templates: [Mustache](https://github.com/samskivert/jmustache) (will be migrated later to [Kotlin typesafe templates](https://github.com/sdeleuze/kotlin-script-templating))
 - Reactive API: [Reactor](http://projectreactor.io/)
 - Persistence : [Spring Data Reactive MongoDB](https://spring.io/blog/2016/11/28/going-reactive-with-spring-data)
 - Build: [Gradle Script Kotlin](https://github.com/gradle/gradle-script-kotlin)
 - Testing: [Junit 5](http://junit.org/)

### TODO

 - Use [Kotlin Javascript](https://kotlinlang.org/docs/reference/js-overview.html) with [dead code elimination](https://kotlinlang.org/docs/reference/javascript-dce.html) tool

## Developer guide

### Prerequisite
 - Install [Git](https://git-scm.com/)
 - Install [Docker](https://www.docker.com/#)
 - [Fork](https://github.com/mix-it/mixit#fork-destination-box) and clone [the project](https://github.com/mix-it/mixit)
 - [Install Java 11](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)

### Start the database
We use a mongodb instance and this database is managed with a docker file
 - Run `docker compose up` to start the database and the console
 - Open `http://0.0.0.0:8081` to open the mongodb console
 - At any moment you can stop and remove and restart the container if you need to reinit the database

### Run the app in dev mod using command line
 - Run `./gradlew bootRun` in another terminal
 - Run `./gradlew watch` in another terminal
 - Open `http://localhost:8080/` in your browser
 - If you want to debug the app, add `--debug-jvm` parameter to Gradle command line

Sass, TypeScript, `messages*.properties` and templates should be live reloaded.

### Import and run the project in IDEA
 - Make sure you have at least IntelliJ IDEA `2017.2.x` and IDEA Kotlin plugin `1.1.4+` (menu Tools -> Kotlin -> configure Kotlin Plugin Updates -> make sure "Stable" channel is selected -> check for updates now -> restart IDE after the update)
 - Import it in IDEA as a Gradle project
 - In IntelliJ IDEA, right click on `Application.kt` then `Run ...` or `Debug ...`
 - Run `./gradlew watch` in another terminal
 - Open `http://localhost:8080/` in your browser

Sass, TypeScript, `messages*.properties` and templates should be live reloaded.

### Package and run the application from the executable JAR:
```
./gradlew clean build
java -jar build/libs/mixit-1.0.0-SNAPSHOT.jar
```

### Deploy the app on  Clever Cloud
> When you merge a PR into `prod` branch (usually from `master` branch) it will trigger a deployment on Clever Cloud.

### Copy PROD data to src/main/resources/data

```
curl https://mixitconf.org/api/blog | python3 -m json.tool > blog.json
curl https://mixitconf.org/api/faq | python3 -m json.tool > faq.json
curl https://mixitconf.org/api/event | python3 -m json.tool > events.json
curl https://mixitconf.org/api/event/images | python3 -m json.tool > events_image.json
curl https://mixitconf.org/api/user | python3 -m json.tool > users.json
curl https://mixitconf.org/api/2024/talk | python3 -m json.tool > talks_2024.json
git commit -a -m "Update data from PROD"
```

## Database

If you need to restore a Clever Cloud archive in your local db, you can follow these steps

* copy the archive in ./db/dump
* restart the container
* use this command
```shell
docker exec -it mongo-mixit mongorestore -u=admin -p=mixit23 --drop --noIndexRestore --archive=/tmp/dump/mongodb_XXXX.archive
```


Paparazzi
========

An Android library to render your application screens without a physical device or emulator.

```kotlin
class LaunchViewTest {
  @get:Rule
  val paparazzi = Paparazzi(
    deviceConfig = PIXEL_5,
    theme = "android:Theme.Material.Light.NoActionBar"
    // ...see docs for more options
  )

  @Test
  fun launchView() {
    val view = paparazzi.inflate<LaunchView>(R.layout.launch)
    // or...
    // val view = LaunchView(paparazzi.context)

    view.setModel(LaunchModel(title = "paparazzi"))
    paparazzi.snapshot(view)
  }

  @Test
  fun launchComposable() {
    paparazzi.snapshot {
      MyComposable()
    }
  }
}
```

See the [project website][paparazzi] for documentation and APIs.

Tasks
-------

```bash
./gradlew sample:testDebug
```

Runs tests and generates an HTML report at `sample/build/reports/paparazzi/` showing all
test runs and snapshots.

```bash
./gradlew sample:recordPaparazziDebug
```

Saves snapshots as golden values to a predefined source-controlled location
(defaults to `src/test/snapshots`).

```bash
./gradlew sample:verifyPaparazziDebug
```

Runs tests and verifies against previously-recorded golden values. Failures generate diffs at `sample/build/paparazzi/failures`.

For more examples, check out the [sample][sample] project.

Git LFS
--------
It is recommended you use [Git LFS][lfs] to store your snapshots.  Here's a quick setup:

```bash
brew install git-lfs
git config core.hooksPath  # optional, confirm where your git hooks will be installed
git lfs install --local
git lfs track "**/snapshots/**/*.png"
git add .gitattributes
```

On CI, you might set up something like:

`$HOOKS_DIR/pre-receive`
```bash
# compares files that match .gitattributes filter to those actually tracked by git-lfs
diff <(git ls-files ':(attr:filter=lfs)' | sort) <(git lfs ls-files -n | sort) >/dev/null

ret=$?
if [[ $ret -ne 0 ]]; then
  echo >&2 "This remote has detected files committed without using Git LFS. Run 'brew install git-lfs && git lfs install' to install it and re-commit your files.";
  exit 1;
fi
```

`your_build_script.sh`
```bash
if [[ is running snapshot tests ]]; then
  # fail fast if files not checked in using git lfs
  "$HOOKS_DIR"/pre-receive
  git lfs install --local
  git lfs pull
fi
```

Jetifier
--------

If using Jetifier to migrate off Support libraries, add the following to your `gradle.properties` to
exclude bundled Android dependencies.

```properties
android.jetifier.ignorelist=android-base-common,common
```

Lottie
--------

When taking screenshots of Lottie animations, you need to force Lottie to not run on a background thread, otherwise Paparazzi can throw exceptions [#494](https://github.com/cashapp/paparazzi/issues/494), [#630](https://github.com/cashapp/paparazzi/issues/630).

```kotlin
@Before
fun setup() {
    LottieTask.EXECUTOR = Executor(Runnable::run)
}
```

LocalInspectionMode
--------
Some Composables -- such as `GoogleMap()` -- check for `LocalInspectionMode` to short-circuit to a `@Preview`-safe Composable.

However, Paparazzi does not set `LocalInspectionMode` globally to ensure that the snapshot represents the true production output, similar to how it overrides `View.isInEditMode` for legacy views.

As a workaround, we recommend wrapping such a Composable in a custom Composable with a `CompositionLocalProvider` and setting `LocalInspectionMode` there.

```kotlin
 @Test
  fun inspectionModeView() {
    paparazzi.snapshot(
      CompositionLocalProvider(LocalInspectionMode provides true) {
        YourComposable()
      }
    )
  }
```

Releases
--------

Our [change log][changelog] has release history.

Using plugin application:
```groovy
buildscript {
  repositories {
    mavenCentral()
    google()
  }
  dependencies {
    classpath 'app.cash.paparazzi:paparazzi-gradle-plugin:1.3.4'
  }
}

apply plugin: 'app.cash.paparazzi'
```

Using the plugins DSL:
```groovy
plugins {
  id 'app.cash.paparazzi' version '1.3.4'
}
```

Snapshots of the development version are available in [Sonatype's `snapshots` repository][snap].

```groovy
repositories {
  // ...
  maven {
    url 'https://oss.sonatype.org/content/repositories/snapshots/'
  }
}
```

License
-------

```
Copyright 2019 Square, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```

 [paparazzi]: https://cashapp.github.io/paparazzi/
 [sample]: https://github.com/cashapp/paparazzi/tree/master/sample
 [lfs]: https://git-lfs.github.com/
 [changelog]: https://cashapp.github.io/paparazzi/changelog/
 [snap]: https://oss.sonatype.org/content/repositories/snapshots/app/cash/paparazzi/


# Kotlin Language Specification

[![JetBrains official project](https://jb.gg/badges/official.svg)](https://github.com/JetBrains#jetbrains-on-github)
[![TeamCity (simple build status)](https://img.shields.io/teamcity/https/teamcity.jetbrains.com/e/Kotlin_Spec_DocsMaster.svg?style=flat)](https://teamcity.jetbrains.com/viewType.html?buildTypeId=Kotlin_Spec_DocsMaster&branch_Kotlin_dev=%3Cdefault%3E&tab=buildTypeStatusDiv)
[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](https://www.apache.org/licenses/LICENSE-2.0)
[![Latest release version](https://img.shields.io/github/v/release/Kotlin/kotlin-spec?style=flat)](https://github.com/Kotlin/kotlin-spec/releases)

This repository contains the specification of the [Kotlin programming language](https://kotlinlang.org), which describes how parts of the language should function *in more detail*, as compared to a more traditional user documentation on the [Kotlin Website](https://kotlinlang.org/docs/reference/).

It would be most useful to those who are interested in how Kotlin works on a finer level and how its features interoperate, e.g., language enthusiasts, compiler writers and Kotlin power-users.
However, if you are simply wondering, why some code you wrote works the way it does, this specification might help you get an answer to that.

Currently, the specification covers only what we call *Kotlin/Core*: fundamental parts of Kotlin which should function the same way irregardless of the underlying platform.
In the future, we plan to extend it with additional platform-specific sections covering Kotlin/JVM, Kotlin/JS and Kotlin/Native.

## Compatibility

Kotlin Language Specification is still in progress and has **experimental** stability level, meaning no compatibility should be expected between even incremental releases, any functionality can be added, removed or changed without warning.

## Artifacts

HTML version of the specification is available on the [Kotlin Website](https://kotlinlang.org/spec).

PDF version can be downloaded using the links in the HTML version or using the [direct link](https://kotlinlang.org/spec/pdf/kotlin-spec.pdf).

## Kotlin grammar

The grammar is a part of the specification and is also contained in this repository.

The reference grammar files in ANTLR4 format are located in the [grammar folder](./grammar/src/main/antlr/).
The human-friendly version is available on the [Kotlin Website](https://kotlinlang.org/docs/reference/grammar.html), in the [HTML](https://kotlinlang.org/spec/syntax-and-grammar.html) or [PDF](https://kotlinlang.org/spec/pdf/sections/syntax-and-grammar.pdf) version of the specification.

## Building the specification

The specification is built using [Gradle](https://gradle.org/).
Therefore, most dependencies are downloaded by the build system.

However, there are several external dependencies which should be installed separately.
For instructions on how to do this, please refer to your operating system documentation.

* [Pandoc](https://pandoc.org/) (tested with version 2.9.1)
* [npm](https://www.npmjs.com/) (tested with version 6.14.6)
* [gpp](https://logological.org/gpp) (tested with version 2.25)
* [bash](https://www.gnu.org/software/bash/) (tested with version 5.0.17)

After installing these dependencies, building the specification is as easy as running:

```
./gradlew buildWeb buildPdf
```

which creates both HTML and PDF versions of the specification in `./build/spec`.

> When doing the build for the very first time, you will see Gradle downloading `ideaIC-LATEST-EAP-SNAPSHOT.zip`, which may take quite a long time.
> This IDEA snapshot is used for specification and grammar tests, and will be cached (until a new version is available), so this lengthy download should happen only once (in a while).

The PDF version is available in two flavours: single-file PDF, containing the complete specification, and a set of section-based PDFs, containing their respective sections.

The HTML version consists of a set of section-based pages linked together via an interactive table of contents.

## Contributing

If you want to contribute to the specification, that's great!
You can help us make the Kotlin specification better by one of the following ways.

1. Create an [issue](https://github.com/Kotlin/kotlin-spec/issues) and describe what you think can be improved
1. Make a [pull request](https://github.com/Kotlin/kotlin-spec/pulls) and extends the specification
1. Discuss the specification on the Kotlin [forums](https://discuss.kotlinlang.org/)
1. Drop an email to [Marat Akhin](mailto:marat.akhin@jetbrains.com) or [Mikhail Belyaev](mailto:mikhail.belyaev@jetbrains.com) with your suggestions

> Note: if doing a pull request, it should be based on the `develop` branch.

We welcome any and all feedback to the specification, but may tweak, change or iterate with you on the contribution before including it in the specification.

Further details on how to contribute to the specification are available in [CONTRIBUTING.md](CONTRIBUTING.md).

## Reference

If one needs to reference this specification, they may use the following:

> Marat Akhin, Mikhail Belyaev et al. "Kotlin language specification: Kotlin/Core", JetBrains / JetBrains Research, 2020


# Vocable AAC for Android
![Platform Android](https://img.shields.io/badge/Platform-Android-blue.svg)
![license MIT](https://img.shields.io/badge/license-MIT-brightgreen.svg)
[![Crowdin](https://badges.crowdin.net/vocable-android/localized.svg)](https://crowdin.com/project/vocable-android)
[![Slack](https://img.shields.io/badge/Join%20our%20Slack-%23E01E5A?logo=slack)](https://docs.google.com/forms/d/1hiU2fJtta4BcalnybFMugUE9RXeG4oQXelG9B3KDtf8/viewform?edit_requested=true)

> Empowering people to communicate with care takers and loved ones.

[![Watch the video](marketing_assets/vocable_vimeo_still.gif)](https://player.vimeo.com/video/394212430)

[![Play Store Link](marketing_assets/google-play-badge.svg)](https://play.google.com/store/apps/details?id=com.willowtree.vocable)

Pre-release builds are available through Firebase [here](https://appdistribution.firebase.dev/i/ebf0696a3e643b20)

## Contents
- [What is Vocable?](#what-is-vocable)
- [Features](#features)
- [Roadmap](#roadmap)
- [Translations](#translations)
- [Contributing](#contributing)
- [Requirements](#requirements)
- [Credits](#credits)
- [License](#license)

## What is Vocable?
Vocable AAC allows those with conditions such as MS, stroke, ALS, or spinal cord injuries to communicate using an app that tracks head movements, without the need to spend tens of thousands of dollars on technology to do so.

## Features

### Multimodal User Interface

Vocable uses ARCore to track the user's head movements and understand where the user is looking at on the screen. This allows the app to be used completely hands-free: users can look around the screen and make selections by lingering their gaze at a particular element.

For users with more mobility, the app can be operated by touch.

### Saved Phrases
Use a list of common phrases provided by speech language pathologists, or create and save your own.

### Full QWERTY Keyboard
Type with your head or your hands.

## Roadmap
For the current progress on features, please visit the [project board](https://github.com/orgs/willowtreeapps/projects/50/views/1).

For a high-level roadmap, see the [Vocable Roadmap](./ROADMAP.md)

## Translations
We'd love to translate Vocable into as many languages as possible. If you'd like to help translate, please visit our [Crowdin project](https://crowdin.com/project/vocable-android). Thanks for helping people communicate all around the world! 🌎🌍🌏

## Contributing
We love contributions! To get started, please see our [Contributing Guidelines](./CONTRIBUTING.md).

## Device Requirements
- [Android devices with ARCore](https://developers.google.com/ar/discover/supported-devices)

## Credits
Matt Kubota, Kyle Ohanian, Duncan Lewis, Ameir Al-Zoubi, and many more from [WillowTree](https://willowtreeapps.com/) 💙.

## License
vocable-android is released under the MIT license. See [LICENSE](LICENSE) for details.

## Other Variants
vocable-ios is available on [Apple Play Store](https://apps.apple.com/us/app/vocable-aac/id1497040547) and is also [open-source](https://github.com/willowtreeapps/vocable-ios).


[![Lines of Code](https://sonar.tryb.de/api/project_badges/measure?project=wuan_bo-android_AYcZZuyTg4e1BA2WvQjK&metric=ncloc&token=ee89146b4ee29206327218b2a499361405b50fb2)](https://sonar.tryb.de/dashboard?id=wuan_bo-android_AYcZZuyTg4e1BA2WvQjK)
[![Coverage](https://sonar.tryb.de/api/project_badges/measure?project=wuan_bo-android_AYcZZuyTg4e1BA2WvQjK&metric=coverage&token=ee89146b4ee29206327218b2a499361405b50fb2)](https://sonar.tryb.de/dashboard?id=wuan_bo-android_AYcZZuyTg4e1BA2WvQjK)

# About

The Android App *Blitzortung Lightning Monitor built from these sources visualizes lightning data provided by the blitzortung.org network.

[](https://f-droid.org/packages/org.blitzortung.android.app/)
[](https://play.google.com/store/apps/details?id=org.blitzortung.android.app)

## Available translations

 * Czech
 * Dutch
 * English
 * French
 * German
 * Hungarian
 * Italian
 * Polish
 * Slovak
 * Russian
 * Spanish

## Translation offers are welcome

We are still looking forward to volunteers preparing a translation for the following languages:

 * yours?

Translations to other languages are welcome as well. Please contact us via `blitzortung at tryb.de`


# Kotlin Spotify Web API
A [Kotlin](https://kotlinlang.org/) implementation of the [Spotify Web API](https://developer.spotify.com/web-api/),
supporting Kotlin/JS, Kotlin/Android, Kotlin/JVM, and Kotlin/Native
(macOS, Windows, Linux).

This library has first-class support for Java and is a viable alternative for Java development.
Please see [the Java section](#java) for more details.

**Use this library in Kotlin, Java, JavaScript, Swift, or native code!** Because this library targets both iOS and Android, it can also be used in KMM ([Kotlin Multiplatform Mobile](https://kotlinlang.org/lp/mobile/)) applications as a shared source.

[![Maven CEntral](https://maven-badges.herokuapp.com/maven-central/com.adamratzman/spotify-api-kotlin-core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.adamratzman/spotify-api-kotlin-core)
[![](https://img.shields.io/badge/Documentation-latest-orange.svg)](https://adamint.github.io/spotify-web-api-kotlin-docs/)
![](https://img.shields.io/badge/License-MIT-blue.svg)
[![codebeat badge](https://codebeat.co/badges/0ab613b0-31d7-4848-aebc-4ed1e51f069c)](https://codebeat.co/projects/github-com-adamint-spotify-web-api-kotlin-master)

## Table of Contents
* [Oerview and how to install](#overview-and-how-to-install)
    + [JVM, Android, JS, Native](#jvm-android-js-native-apple)
    + [Android information](#android)
      * [Android sample app](#android-sample-application)
* [Documentation](#documentation)
* [Need help, have a question, or want to contribute?](#have-a-question)
* [Creating a new api instance](#creating-a-new-api-instance)
    + [SpotifyAppApi](#spotifyappapi)
    + [SpotifyClientApi](#spotifyclientapi)
        * [PKCE](#pkce)
        * [Non-PKCE](#non-pkce-backend-applications-requires-client-secret)
    + [SpotifyImplicitGrantApi](#spotifyimplicitgrantapi)
    + [SpotifyApiBuilder block & setting API options](#spotifyapibuilder-block--setting-api-options)
        * [API options](#api-options)
    + [Using the API](#using-the-api)
* [Platform-specific wrappers and information](#platform-specific-wrappers-and-information)
    + [Java](#java)
    + [Android authentication](#android-authentication)
    + [JavaScript: Spotify Web Playback SDK wrapper](#js-spotify-web-playback-sdk-wrapper)
* [Tips](#tips)
    + [Building the API](#building-the-api)
* [Notes](#notes)
    + [LinkedResults, PagingObjects, and Cursor-based Paging Objects](#the-benefits-of-linkedresults-pagingobjects-and-cursor-based-paging-objects)
    + [Generic Requests](#generic-request)
    + [Track Relinking](#track-relinking)
* [Contributing](#contributing)

## Overview and how to install
Current version:

[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.adamratzman/spotify-api-kotlin-core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.adamratzman/spotify-api-kotlin-core)

### JVM, Android, JS, Native, Apple
```
repositories {
    mavenCentral()
}

implementation("com.adamratzman:spotify-api-kotlin-core:VERSION")
```

### JS
Please see the [JS Spotify Web Playback SDK wrapper](#js-spotify-web-playback-sdk-wrapper) to learn how to use Spotify's web playback SDK in a browser application.

### Android
**Note**: For information on how to integrate implicit/PKCE authentication, Spotify app remote, and Spotify broadcast notifications into
your application, please see the [Android README](README_ANDROID.md).

*If you declare any release types not named debug or release, you may see "Could not resolve com.adamratzman:spotify-api-kotlin-android:VERSION". You need to do the following for each release type not named debug or release:*
```
android {
    buildTypes {
        yourReleaseType1 {
            // ...
            matchingFallbacks = ['release', 'debug']
        }
        yourReleaseType2 {
            // ...
            matchingFallbacks = ['release', 'debug']
        }
	...
    }
}
```

To successfully build, you might need to exclude kotlin_module files from the packaging. To do this, inside the android/buildTypes/release closure, you would put:
```
packagingOptions {
	exclude 'META-INF/*.kotlin_module'
}
```

#### Android sample application
You can find a simple sample application demonstrating how to use spotify-web-api-kotlin in a modern Android app, as well as how to integrate with the Spotify app, [here](https://github.com/Nielssg/Spotify-Api-Test-App).

## Documentation
The `spotify-web-api-kotlin` JavaDocs are hosted [here](https://adamint.github.io/spotify-web-api-kotlin-docs/).

## Have a question?
If you have a question, you can:

1. Create an [issue](https://github.com/adamint/spotify-web-api-kotlin/issues)
2. Join our [Discord server](https://discord.gg/G6vqP3S)
3. Contact me using **Adam#9261** on [Discord](https://discordapp.com)

## Unsupported features on each platform:
| Feature                     | JVM                | Android            | JS                 | Native (Mac/Windows/Linux) |
|-----------------------------|--------------------|--------------------|--------------------|----------------------------|
| Edit client playlist        | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | Unsupported                |
| Remove playlist tracks      | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | Unsupported                |

Please feel free to open an issue/discussion on GitHub or Discord if you need access to one of these features
or have an interest in implementing one, as direction can be provided.

## Creating a new api instance
To decide which api you need (SpotifyAppApi, SpotifyClientApi, SpotifyImplicitGrantApi), you can refer
to the sections below or the [Spotify authorization guide](https://developer.spotify.com/documentation/general/guides/authorization-guide/). In general:
- If you don't need client resources, use SpotifyAppApi
- If you're using the api in a backend application, use SpotifyClientApi (with or without PKCE)
- If you're using the api in Kotlin/JS browser, use SpotifyImplicitGrantApi
- If you need access to client resources in an Android or other application, use SpotifyClientApi with PKCE

**Note**: You can use the online [Spotify OAuth Token Generator](https://adamratzman.com/projects/spotify/generate-token) tool to generate a client token for local testing.

### SpotifyAppApi
This provides access only to public Spotify endpoints.
Use this when you have a server-side application. Note that implicit grant authorization
provides a higher api ratelimit, so consider using implicit grant if your application has
significant usage.

By default, the SpotifyApi `Token` automatically regenerates when needed.
This can be changed by overriding the `automaticRefresh` builder setting.

There are four exposed builders, depending on the level of control you need over api creation.
Please see the [spotifyAppApi builder docs](https://adamint.github.io/spotify-web-api-kotlin-docs/spotify-web-api-kotlin/com.adamratzman.spotify/-spotify-app-api/index.html) for a full list of available builders.

You will need:
- Spotify application client id
- Spotify application client secret

Example creation (default settings)

```kotlin
val api = spotifyAppApi("clientId", "clientSecret").build() // create and build api
println(api.browse.getNewReleases()) // use it
```

Example creation, using an existing Token and setting automatic token refresh to false
```kotlin
val token = spotifyAppApi(spotifyClientId, spotifyClientSecret).build().token
val api = spotifyAppApi(
  "clientId",
  "clientSecret",
  token
) {
  automaticRefresh = false
}.build()

println(api.browse.getNewReleases()) // use it
```

### SpotifyClientApi
The `SpotifyClientApi` is a superset of `SpotifyApi`; thus, nothing changes if you want to
access public data.
This library does not provide a method to retrieve the code from your  callback url; instead,
you must implement that with a web server.
Automatic Token refresh is available *only* when building with an authorization code or a
`Token` object. Otherwise, it will expire `Token.expiresIn` seconds after creation.

Make sure your application has requested the proper [Scopes](https://developer.spotify.com/web-api/using-spotifyScopes/) in order to
ensure proper function of this library. The api option `requiredScopes` allows you to verify
that a client has actually authorized with the scopes you are expecting.

You will need:
- Spotify application client id
- Spotify application client secret (if not using PKCE)
- Spotify application redirect uri
- To choose which client authorization method (PKCE or non-PKCE) to use

#### PKCE
Use the PKCE builders and helper methods if you are using the Spotify client authorization PKCE flow.
Building via PKCE returns a `SpotifyClientApi` which has modified refresh logic.

Use cases:
1. You are using this library in an application (likely Android), or do not want to expose the client secret.

To learn more about the PKCE flow, please read the [Spotify authorization guide](https://developer.spotify.com/documentation/general/guides/authorization-guide/#implicit-grant-flow).
Some highlights about the flow are:
- It is refreshable, but each refresh token can only be used once. This library handles token refresh automatically by default
- It does not require a client secret; instead, a set redirect uri and a random code verifier
are used to verify the authenticity of the authorization.
- A code verifier is required. The code verifier is "*a cryptographically random string between 43 and 128 characters in length.
It can contain letters, digits, underscores, periods, hyphens, or tildes.*"
- A code challenge is required. "*In order to generate the code challenge, your app should
hash the code verifier using the SHA256 algorithm. Then, base64url encode the hash that you generated.*"
- When creating a pkce api instance, the code verifier is passed in by you and compared to
the code challenge used to authorize the user.

This library contains helpful methods that can be used to simplify the PKCE authorization process.
This includes `getSpotifyPkceCodeChallenge`, which SHA256 hashes and base64url encodes the code
challenge, and `getSpotifyPkceAuthorizationUrl`, which allows you to generate an easy authorization url for PKCE flow.

Please see the [spotifyClientPkceApi builder docs](https://adamint.github.io/spotify-web-api-kotlin-docs/spotify-web-api-kotlin/com.adamratzman.spotify/spotify-client-pkce-api.html) for a full list of available builders.

**Takeaway**: Use PKCE authorization flow in applications where you cannot secure the client secret.

To get a PKCE authorization url, to which you can redirect a user, you can use the `getSpotifyPkceAuthorizationUrl`
top-level method. An example is shown below, requesting 4 different scopes.
```kotlin
val codeVerifier = "thisisaveryrandomalphanumericcodeverifierandisgreaterthan43characters"
val codeChallenge = getSpotifyPkceCodeChallenge(codeVerifier) // helper method
val url: String = getSpotifyPkceAuthorizationUrl(
    SpotifyScope.PLAYLIST_READ_PRIVATE,
    SpotifyScope.PLAYLIST_MODIFY_PRIVATE,
    SpotifyScope.USER_FOLLOW_READ,
    SpotifyScope.USER_LIBRARY_MODIFY,
    clientId = "clientId",
    redirectUri = "your-redirect-uri",
    codeChallenge = codeChallenge
)
```

There is also an optional parameter `state`, which helps you verify the authorization.

**Note**: If you want automatic token refresh, you need to pass in your application client id and redirect uri
when using the `spotifyClientPkceApi`.

##### Example: A user has authorized your application. You now have the authorization code obtained after the user was redirected back to your application. You want to create a new `SpotifyClientApi`.
```kotlin
val codeVerifier = "thisisaveryrandomalphanumericcodeverifierandisgreaterthan43characters"
val code: String = ...
val api = spotifyClientPkceApi(
    "clientId", // optional. include for token refresh
    "your-redirect-uri", // optional. include for token refresh
    code,
    codeVerifier // the same code verifier you used to generate the code challenge
) {
  retryWhenRateLimited = false
}.build()

println(api.library.getSavedTracks().take(10).filterNotNull().map { it.track.name })
```

#### Non-PKCE (backend applications, requires client secret)
To get a non-PKCE authorization url, to which you can redirect a user, you can use the `getSpotifyAuthorizationUrl`
top-level method. An example is shown below, requesting 4 different scopes.
```kotlin
val url: String = getSpotifyAuthorizationUrl(
    SpotifyScope.PLAYLIST_READ_PRIVATE,
    SpotifyScope.PLAYLIST_MODIFY_PRIVATE,
    SpotifyScope.USER_FOLLOW_READ,
    SpotifyScope.USER_LIBRARY_MODIFY,
    clientId = "clientId",
    redirectUri = "your-redirect-uri",
    state = "your-special-state" // optional
)
```
There are also several optional parameters, allowing you to set whether the authorization url is meant
for implicit grant flow, the state, and whether a re-authorization dialog should be shown to users.

There are several exposed builders, depending on the level of control you need over api creation.
Please see the [spotifyClientApi builder docs](https://adamint.github.io/spotify-web-api-kotlin-docs/spotify-web-api-kotlin/com.adamratzman.spotify/spotify-client-api.html) for a full list of available builders.

##### Example: You've redirected the user back to your web server and have an authorization code (code).
In this example, automatic token refresh is turned on by default.
```kotlin
val authCode = ""
val api = spotifyClientApi(
    "clientId",
    "clientSecret",
    "your-redirect-uri",
    authCode
).build() // create and build api
println(api.personalization.getTopTracks(limit = 5).items.map { it.name }) // print user top tracks
```

##### Example: You've saved a user's token from previous authorization and need to create an api instance.
In this case, if you provide a client id to the builder, automatic token refresh will also be turned on.
```kotlin
val token: Token = ... // your existing token
val api = spotifyClientApi(
    "clientId",
    "clientSecret",
    "your-redirect-uri",
    token
) {
  onTokenRefresh = {
    println("Token refreshed at ${System.currentTimeMillis()}")
  }
}.build()
println(api.personalization.getTopTracks(limit = 5).items.map { it.name })
```

### SpotifyImplicitGrantApi
Use the `SpotifyImplicitGrantApi` if you are using the Spotify implicit grant flow.
`SpotifyImplicitGrantApi` is a superset of `SpotifyClientApi`.
Unlike the other builders, the `spotifyImplicitGrantApi` builder method directly returns
a `SpotifyImplicitGrantApi` instead of an api builder.

Use cases:
1. You are using the **Kotlin/JS** target for this library.
2. Your frontend Javascript passes the token received through the implicit grant flow to your
backend, where it is then used to create an api instance.

To learn more about the implicit grant flow, please read the [Spotify authorization guide](https://developer.spotify.com/documentation/general/guides/authorization-guide/#implicit-grant-flow).
Some highlights about the flow are:
- It is non-refreshable
- It is client-side
- It does not require a client secret

Please see the [spotifyImplicitGrantApi builder docs](https://adamint.github.io/spotify-web-api-kotlin-docs/spotify-web-api-kotlin/com.adamratzman.spotify/spotify-implicit-grant-api.html) for a full list of available builders.

The Kotlin/JS target contains the `parseSpotifyCallbackHashToToken` method, which will parse the hash
for the current url into a Token object, with which you can then instantiate the api.

**Takeaway**: There are two ways to use implicit grant flow, browser-side only and browser and
server. This library provides easy access for both.

##### Example
```kotlin
val token: Token = ...
val api = spotifyImplicitGrantApi(
    null,
    null,
    token
) // create api. there is no need to build it
println(api.personalization.getTopArtists(limit = 1)[0].name) // use it
```

### SpotifyApiBuilder Block & setting API options
There are three pluggable blocks in each api's corresponding builder

1. `credentials` lets you set the client id, client secret, and redirect uri
2. `authorization` lets you set the type of api authorization you are using.
Acceptable types include: an authorization code, a `Token` object, a Token's access code string, and an optional refresh token string
3. `options` lets you configure API options to your own specific needs

#### API options
This library does not attempt to be prescriptivist.
All API options are located in `SpotifyApiOptions` and their default values can be overridden; however, use caution in doing so, as
most of the default values either allow for significant performance or feature enhancements to the API instance.

- `useCache`: Set whether to cache requests. Default: true
- `cacheLimit`: The maximum amount of cached requests allowed at one time. Null means no limit. Default: 200
- `automaticRefresh`: Enable or disable automatic refresh of the Spotify access token when it expires. Default: true
- `retryWhenRateLimited`: Set whether to block the current thread and wait until the API can retry the request. Default: true
- `enableLogger`: Set whether to enable to the exception logger. Default: true
- `testTokenValidity`: After API creation, test whether the token is valid by performing a lightweight request. Default: false
- `defaultLimit`: The default amount of objects to retrieve in one request. Default: 50
- `json`: The Json serializer/deserializer instance.
- `allowBulkRequests`: Allow splitting too-large requests into smaller, allowable api requests. Default: true
- `requestTimeoutMillis`: The maximum time, in milliseconds, before terminating an http request. Default: 100000ms
- `refreshTokenProducer`: Provide if you want to use your own logic when refreshing a Spotify token.
- `requiredScopes`: Scopes that your application requires to function (only applicable to `SpotifyClientApi` and `SpotifyImplicitGrantApi`).
This verifies that the token your user authorized with actually contains the scopes your
application needs to function.

Notes:
- Unless you have a good reason otherwise, `useCache` should be true
- `cacheLimit` is per Endpoint, not per API. Don't be surprised if you end up with over 200 items in your cache with the default settings.
- `automaticRefresh` is disabled when client secret is not provided, or if tokenString is provided in SpotifyClientApi
- `allowBulkRequests` for example, lets you query 80 artists in one wrapper call by splitting it into 50 artists + 30 artists
- `refreshTokenProducer` is useful when you want to re-authorize with the Spotify Auth SDK or elsewhere

### Using the API
APIs available in all `SpotifyApi` instances, including `SpotifyClientApi` and `SpotifyImplicitGrantApi`:
- `SearchApi` (searching items)
- `AlbumApi` (get information about albums)
- `BrowseApi` (browse new releases, featured playlists, categories, and recommendations)
- `ArtistApi` (get information about artists)
- `PlaylistApi` (get information about playlists)
- `UserApi` (get public information about users on Spotify)
- `TrackApi` (get information about tracks)
- `FollowingApi` (check whether users follow playlists)

APIs available only in `SpotifyClientApi` and `SpotifyImplicitGrantApi` instances:
- `ClientSearchApi` (all the methods in `SearchApi`, and searching shows and episodes)
- `EpisodeApi` (get information about episodes)
- `ShowApi` (get information about shows)
- `ClientPlaylistApi` (all the methods in `PlaylistApi`, and get and manage user playlists)
- `ClientProfileApi` (all the methods in `UserApi`, and get the user profile, depending on scopes)
- `ClientFollowingApi` (all the methods in `FollowingApi`, and get and manage following of playlists, artists, and users)
- `ClientPersonalizationApi` (get user top tracks and artists)
- `ClientLibraryApi` (get and manage saved tracks and albums)
- `ClientPlayerApi` (view and control Spotify playback)

## Platform-specific wrappers and information

### Java
This library has first-class support for Java! You have two choices when using this library: async-only with Kotlin
suspend functions (using SpotifyContinuation).

#### Integrating with Kotlin suspend functions via Java `Continuation`s
Unfortunately, coroutines don't play very nicely with Java code. Fortunately, however, we provide a wrapper around Kotlin's
`Continuation` class that allows you to directly implement `onSuccess` and `onFailure` handlers on API methods.

Please see below for an example:

```java
import com.adamratzman.spotify.SpotifyApiBuilderKt;
import com.adamratzman.spotify.SpotifyAppApi;
import com.adamratzman.spotify.javainterop.SpotifyContinuation;
import com.adamratzman.spotify.models.Album;
import org.jetbrains.annotations.NotNull;

import java.util.concurrent.ExecutionException;

public class SpotifyTestApp {
    static SpotifyAppApi api;

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        var id = "spotify-client-id";
        var secret = "spotify-client-secret";
        SpotifyApiBuilderKt.spotifyAppApi(id, secret).build(true, new SpotifyContinuation<>() {
            @Override
            public void onSuccess(SpotifyAppApi spotifyAppApi) {
                api = spotifyAppApi;
                runAlbumSearch();
            }

            @Override
            public void onFailure(@NotNull Throwable throwable) {
                throwable.printStackTrace();
            }
        });

        Thread.sleep(1000000);
    }

    public static void runAlbumSearch() {
        api.getAlbums().getAlbum("spotify:album:0b23AHutIA1BOW0u1dZ6wM", null, new SpotifyContinuation<>() {
            @Override
            public void onSuccess(Album album) {
                System.out.println("Album name is: " + album.getName() + ". Exiting now..");

                System.exit(0);
            }

            @Override
            public void onFailure(@NotNull Throwable throwable) {
                throwable.printStackTrace();
            }
        });
    }
}
```

### Android authentication
For information on how to integrate implicit/PKCE authentication, Spotify app remote, and Spotify broadcast notifications into
your application, please see the [Android README](README_ANDROID.md).

### JS Spotify Web Playback SDK wrapper
`spotify-web-api-kotlin` provides a wrapper around Spotify's [Web Playback SDK](https://developer.spotify.com/documentation/web-playback-sdk/reference/)
for playing music via Spotify in the browser on your own site.

To do this, you need to create a `Player` instance and then use the associated methods to register listeners, play,
and get current context.

Please see an example of how to do this [here](https://github.com/adamint/spotify-web-api-browser-example/blob/95df60810611ddb961a7a2cb0c874a76d4471aa7/src/main/kotlin/com/adamratzman/layouts/HomePageComponent.kt#L38).
An example project, [spotify-web-api-browser-example](https://github.com/adamint/spotify-web-api-browser-example),
demonstrates how to create a frontend JS Kotlin application with Spotify integration and
that will play music in the browser.

**Notes**:
1. You must include the Spotify player JS script by including `<script src="https://sdk.scdn.co/spotify-player.js"></script>`
2. You must define a `window.onSpotifyWebPlaybackSDKReady` function immediately afterwards - this should load your main application bundle.
    Otherwise, you will get errors. An example is below:

```html
<html>
<head>
    ...
    <script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>

    <script>
        jQuery.loadScript = function (url, callback) {
            jQuery.ajax({
                url: url,
                dataType: 'script',
                success: callback,
                async: true
            });
        }
    </script>

    <script src="https://sdk.scdn.co/spotify-player.js"></script>
    <script>
        window.onSpotifyWebPlaybackSDKReady = () => {
            $.loadScript("main.bundle.js")
        }
    </script>
</head>
<body>
....
</body>
</html>
```

## Tips

### Building the API
The easiest way to build the API is using .build() after a builder
```kotlin
runBlocking {
    val api = spotifyAppApi(clientId, clientSecret).build()
}
```

## Notes
### Re-authentication
If you are using an authorization flow or token that does not support automatic token refresh, `SpotifyException.ReAuthenticationNeededException`
will be thrown. You should put your requests, if creating an application, behind a try/catch block to re-authenticate users if this
exception is thrown.

### LinkedResults, PagingObjects, and Cursor-based Paging Objects
Spotify provides these three object models in order to simplify our lives as developers. So let's see what we
can do with them!

#### PagingObjects
PagingObjects are a container for the requested objects (`items`), but also include
important information useful in future calls. It contains the request's `limit` and `offset`, along with
(sometimes) a link to the next and last page of items and the total number of items returned.

If a link to the next or previous page is provided, we can use the `getNext` and `getPrevious` methods to retrieve
the respective PagingObjects

#### Cursor-Based Paging Objects
A cursor-based paging object is a PagingObject with a cursor added on that can be used as a key to find the next
page of items. The value in the cursor, `after`, describes after what object to begin the query.

Just like with PagingObjects, you can get the next page of items with `getNext`. *However*, there is no
provided implementation of `after` in this library. You will need to do it yourself, if necessary.

#### LinkedResults
Some endpoints, like `PlaylistAPI.getPlaylistTracks`, return a LinkedResult, which is a simple wrapper around the
list of objects. With this, we have access to its Spotify API url (with `href`), and we provide simple methods to parse
that url.

### Generic Request
For obvious reasons, in most cases, making asynchronous requests via `queue` or `queueAfter` is preferred. However,
the synchronous format is also shown.

```kotlin
val api = spotifyAppApi(
        System.getenv("SPOTIFY_CLIENT_ID"),
        System.getenv("SPOTIFY_CLIENT_SECRET")
).build()

// print out the names of the twenty most similar songs to the search
println(api.search.searchTrack("Début de la Suite").joinToString { it.name })

// simple, right? what about if we want to print out the featured playlists message from the "Overview" tab?
println(api.browse.getFeaturedPlaylists().message)

// easy! let's try something a little harder
// let's find out Bénabar's Spotify ID, find his top tracks, and print them out
val benabarId = api.search.searchArtist("Bénabar")[0].id
// this works; a redundant way would be: api.artists.getArtist("spotify:artist:6xoAWsIOZxJVPpo7Qvqaqv").id
println(api.artists.getArtistTopTracks(benabarId).joinToString { it.name })
```

### Track Relinking
Spotify keeps many instances of most tracks on their servers, available in different markets. As such, if we use endpoints
that return tracks, we do not know if these tracks are playable in our market. That's where track relinking comes in.

To relink in a specified market, we must supply a `market` parameter for endpoints where available.
In both Track and SimpleTrack objects in an endpoint response, there is a nullable field called `linked_from`.
If the track is unable to be played in the specified market and there is an alternative that *is* playable, this
will be populated with the href, uri, and, most importantly, the id of the track.

You can then use this track in `SpotifyClientApi` endpoints such as playing or saving the track, knowing that it will be playable
in your market!

## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md)


[![stable](https://img.shields.io/badge/lifecycle-STABLE-green.svg)](https://github.com/holisticon#open-source-lifecycle)
[![Master and Snapshot release](https://github.com/holunda-io/camunda-bpm-taskpool/actions/workflows/release.yml/badge.svg)](https://github.com/holunda-io/camunda-bpm-taskpool/actions/workflows/release.yml)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.holunda.polyflow/polyflow-taskpool-dependencies/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.holunda.polyflow/polyflow-taskpool-dependencies/)
[![Code Coverage](https://codecov.io/gh/holunda-io/camunda-bpm-taskpool/branch/master/graph/badge.svg)](https://codecov.io/gh/holunda-io/camunda-bpm-taskpool)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/6e15ca2f4ab64cfe85a736f324136086)](https://www.codacy.com/gh/holunda-io/camunda-bpm-taskpool/dashboard?utm_source=github.com&utm_medium=referral&utm_content=holunda-io/camunda-bpm-taskpool&utm_campaign=Badge_Grade)
[![OpenHUB](https://www.openhub.net/p/camunda-bpm-taskpool/widgets/project_thin_badge.gif)](https://www.openhub.net/p/camunda-bpm-taskpool)

![Logo](docs/img/Positive@2x.png)
## Polyflow Taskpool and Datapool

> A component library for building enterprise-wide process platforms with multiple process engines like Camunda Platform.

In the last years, we built different process applications on behalf of the customer several times. It turned out that some issues occurred every
time during the implementation.

These were:

* coping with performance issues if big amount of tasks is available
* creating high-performance custom queries for pre-loading process variables for tasks
* creating high-performance custom queries to pre-load business data associated with the process instance
* high-performance retrieving a list of tasks from several process engines
* repetitive queries with same result
* creating an archive view for business data items handled during the process execution
* creating an audit log of changes performed on business data items

![Polyflow Hero](docs/img/polyflow-hero-530x406.png)

We decided to stop repetitive work and release an open-source library which builds a foundation for solving these problems.

### Features

* User task API providing attributes important for processing
* Mirroring tasks: provides a copy of all tasks in the system
* Reacts on all task life cycle events fired by the process engine
* High performance queries: creates read-optimized projections including task-, process- and business data
* Centralized task list: allows collecting tasks from multiple engines
* Data enrichment: enrich tasks with business data
* Data entries API providing attributes important for processing
* Audit-Trail creation on business event emission

### Where to start

Sounds interesting for you? If you want to try it out, please read the
[Getting Started](https://www.holunda.io/camunda-bpm-taskpool/stable/getting-started/) section.

### Getting more help

If you have any questions regarding the main concepts, configuration of individual components of Polyflow, please have a look on
the [Reference Guide](https://www.holunda.io/camunda-bpm-taskpool/stable/reference-guide/) acting as a primary documentation. If you want to have a technical
discussion on any issue, feel free to look into [GitHub Project Discussion](https://github.com/holunda-io/camunda-bpm-taskpool/stable/discussions/)

Finally, there are:
- [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/holunda-io/camunda-bpm-taskpool?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
- [![Slack](https://img.shields.io/badge/slack-@holunda/taskpool-green.svg?logo=slack")](https://holunda.slack.com/messages/taskpool/)

available, if you want to discuss more issues with the developers.

### Working Example

Studying and understanding the functionality is easier if you start with our working example described in
the [Example Section](https://www.holunda.io/camunda-bpm-taskpool/stable/examples/).

### License

This library is developed under

[![Apache 2.0 License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](/LICENSE)

### Contribution

This project is open source and we love if the community contributes to this project. If you are willing to help, start
with [Developer Guide](https://www.holunda.io/camunda-bpm-taskpool/stable/developer-guide/contribution.html).

### Sponsors and Customers

[![sponsored](https://img.shields.io/badge/sponsoredBy-Holisticon-red.svg)](https://holisticon.de/)


CatchUp
=======

An app for catching up on things.

https://www.zacsweers.dev/catching-up-on-catchup-introduction/

## Motivations

There's a lot of services I like reading up on throughout the day. Most of these services have
dedicated apps for consuming them, but often times I just want to skim the front page and only deep
dive occasionally. Enter CatchUp: a high level presentation of the "front page" of several services
in short form, and intelligent deeplinking into dedicated apps if you want to go further.

CatchUp is not an all-purpose client for each of these services, just the concierge for at-a-glance
details and router for getting on your way. It does not support login for any service, it does not
support customization/filtering of their feed. CatchUp is dumb, and you should use one of the many
great dedicated apps for this if you want more integration features.

CatchUp is also very much a testing ground for things I personally dive into, from architecture,
libraries, patterns, API quirks, and more. It's been a very fun project to spike test new things.

## Features

- Multiple services
- Hacker News
- Reddit
- Medium
- Product Hunt
- Slashdot
- Designer News
- Dribbble
- GitHub
- Infinite scrolling on supported services
- Pleasant, simple, consistent UI for across services
- Night mode
- Smart deeplinking into dedicated apps

## Technologies

- Kotlin
- Kotlin Coroutines
- Debugging tooling as a first class citizen in the debug build
- Leak Canary, Scalpel, debug drawer, Flipper, bug reporting, the works
- AndroidX/Jetpack
- Dagger 2 + Anvil
- One of the more interesting parts of CatchUp is that its service architecture is a Dagger-powered plugin system
- SqlDelight
- Firebase
- Coil
- Apollo GraphQL
- Standard Square buffet of Okio/OkHttp 3/Retrofit 2/Moshi
- Inspector
- KSP

There's a lot of neat/interesting little tidbits in the CatchUp source code that I plan to write a
mini blog series about. Each service has its own nuances that make them unique to work with in code.

## Testing

While this is a personal pet project, extensive tests can be found [here](https://youtu.be/oHg5SJYRHA0).

## Influences

This app owes a lot of its inspiration, implementation details, and general inner workings to the
work of others. Particularly:
- [Nick Butcher](https://twitter.com/@crafty) and his [Plaid](https://github.com/nickbutcher/plaid) app
- [Jake Wharton](https://twitter.com/@jakewharton) and his [u2020](https://github.com/jakewharton/u2020) demo app

## Development

If you'd like to build CatchUp locally, you _should_ be able to just clone and build with no
issues. The project requires whatever JDK version is currently defined `libs.versions.toml`.

CatchUp tends to keep up with Android Studio canaries, so you may have to use a canary version.
Check the AGP version in `libs.versions.toml`.

If you want to build with working services, some require API keys. See the
[wiki](https://github.com/ZacSweers/CatchUp/wiki/Authentication-information) for more details on
which services require keys.

Bug fixes are always welcome. Tests are too if you're into that kinda thing, but I'm not actively
trying to make this project a shining icon of TDD. For new features or otherwise significant work,
please discuss in an issue first.

License
-------

	Copyright (C) 2017 Zac Sweers

	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at

	http://www.apache.org/licenses/LICENSE-2.0

	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.