onesignal

package module
v0.0.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 26, 2020 License: GPL-3.0 Imports: 10 Imported by: 0

README

Go client for the OneSignal API Build Status GoDoc

This library provides a simple SDK to access the OneSignal API.

Installation

go get -u github.com/genesor/onesignal

Documentation

https://godoc.org/github.com/genesor/onesignal

License

Please see LICENSE for licensing details.

Documentation

Overview

Package onesignal provides the binding for OneSignal API.

Create a new OneSignal client:

client := onesignal.NewClient(nil)

Set the UserKey if you want to use the /apps endpoints:

client.UserKey = "YourOneSignalUserKey"

Set the AppKey for the other endpoints:

client.AppKey = "YourOneSignalAppKey"

Apps

List apps:

apps, res, err := client.Apps.List()

Get an app:

app, res, err := client.Apps.Get("YourAppID")

Create an app:

appRequest := &onesignal.AppRequest{
	Name: "Your app 1",
}
app, res, err := client.Apps.Create(appRequest )

Update an app:

appRequest := &onesignal.AppRequest{
	Name: "Your app 1 modified",
}
app, res, err := client.Apps.Update(appID, appRequest)

Players

List players:

listOpt := &onesignal.PlayerListOptions{
	AppID:  appID,
	Limit:  10,
	Offset: 0,
}
listRes, res, err := client.Players.List(listOpt)

Get player:

player, res, err := client.Players.Get("playerID")

Create player:

playerRequest := &onesignal.PlayerRequest{
	AppID:        "appID",
	DeviceType:   1,
	Identifier:   "fakeidentifier2",
	Language:     "fake-language",
	Timezone:     -28800,
	GameVersion:  "1.0",
	DeviceOS:     "iOS",
	DeviceModel:  "iPhone5,2",
	AdID:         "fake-ad-id2",
	SDK:          "fake-sdk",
	SessionCount: 1,
	Tags: map[string]string{
		"a":   "1",
		"foo": "bar",
	},
	AmountSpent: 1.99,
	CreatedAt:   1395096859,
	Playtime:    12,
	BadgeCount:  1,
	LastActive:  1395096859,
	TestType:    1,
}
createRes, res, err := client.Players.Create(playerRequest)

Create a new session for a player:

opt := &onesignal.PlayerOnSessionOptions{
	Identifier:  "FakeIdentifier",
	Language:    "en",
	Timezone:    -28800,
	GameVersion: "1.0",
	DeviceOS:    "7.0.4",
	AdID:        "fake-ad-id",
	SDK:         "fake-sdk",
	Tags: map[string]string{
		"a":   "1",
		"foo": "bar",
	},
}
successRes, res, err := client.Players.OnSession(playerID, opt)

Create a new purchase for a player:

p1 := onesignal.Purchase{
	SKU:    "foosku1",
	Amount: 1.99,
	ISO:    "BEL",
}
p2 := onesignal.Purchase{
	SKU:    "foosku2",
	Amount: 2.99,
	ISO:    "GER",
}
opt := &onesignal.PlayerOnPurchaseOptions{
	Purchases: []onesignal.Purchase{p1, p2},
	Existing:  true,
}
successRes, res, err := client.Players.OnPurchase(playerID, opt)

Increment the total session length for a player:

opt := &onesignal.PlayerOnFocusOptions{
	State:      "ping",
	ActiveTime: 60,
}
successRes, res, err := client.Players.OnFocus(playerID, opt)

Generate a link to download a CSV list of all the players:

opt := &onesignal.PlayerCSVExportOptions{
	AppID: appID,
}
CSVEXportRes, res, err := client.Players.CSVExport(opt)

Update a player:

player := &onesignal.PlayerRequest{
	GameVersion: "1.3",
}
successRes, res, err := client.Players.Update(playerID, player)

Notifications

List notifications:

listOpt := &onesignal.NotificationListOptions{
	AppID:  appID,
	Limit:  10,
	Offset: 0,
}
listRes, res, err := client.Notifications.List(listOpt)

Get a notification:

opt := &onesignal.NotificationGetOptions{
	AppID: appID,
}
notification, res, err := client.Notifications.Get(notificationID, opt)

Create a notification:

playerID := "aPlayerID"
notificationReq := &onesignal.NotificationRequest{
	AppID:            appID,
	Contents:         map[string]string{"en": "English message"},
	IsIOS:            true,
	IncludePlayerIDs: []string{playerID},
}
createRes, res, err := client.Notifications.Create(notificationReq)

Update a notification:

opt := &onesignal.NotificationUpdateOptions{
	AppID:  appID,
	Opened: true,
}
successRes, res, err := client.Notifications.Update(notificationID, opt)

Delete a notification:

opt := &onesignal.NotificationDeleteOptions{
	AppID: appID,
}
successRes, res, err := client.Notifications.Delete(notificationID, opt)

Package onesignal provides the binding for OneSignal API.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CheckResponse

func CheckResponse(r *http.Response) error

CheckResponse checks the API response for errors, and returns them if present. A response is considered an error if it has a status code outside the 200 range. API error responses are expected to have either no response body, or a JSON response body that maps to ErrorResponse. Any other response body will be silently ignored.

Types

type App

type App struct {
	ID                               string    `json:"id"`
	Name                             string    `json:"name"`
	Players                          int       `json:"players"`
	MessagablePlayers                int       `json:"messagable_players"`
	UpdatedAt                        time.Time `json:"updated_at"`
	CreatedAt                        time.Time `json:"created_at"`
	GCMKey                           string    `json:"gcm_key"`
	ChromeKey                        string    `json:"chrome_key"`
	ChromeWebOrigin                  string    `json:"chrome_web_origin"`
	ChromeWebGCMSenderID             string    `json:"chrome_web_gcm_sender_id"`
	ChromeWebDefaultNotificationIcon string    `json:"chrome_web_default_notification_icon"`
	ChromeWebSubDomain               string    `json:"chrome_web_sub_domain"`
	APNSEnv                          string    `json:"apns_env"`
	APNSCertificates                 string    `json:"apns_certificates"`
	SafariAPNSCertificate            string    `json:"safari_apns_cetificate"`
	SafariSiteOrigin                 string    `json:"safari_site_origin"`
	SafariPushID                     string    `json:"safari_push_id"`
	SafariIcon1616                   string    `json:"safari_icon_16_16"`
	SafariIcon3232                   string    `json:"safari_icon_32_32"`
	SafariIcon6464                   string    `json:"safari_icon_64_64"`
	SafariIcon128128                 string    `json:"safari_icon_128_128"`
	SafariIcon256256                 string    `json:"safari_icon_256_256"`
	SiteName                         string    `json:"site_name"`
	BasicAuthKey                     string    `json:"basic_auth_key"`
}

App represents a OneSignal app.

type AppRequest

type AppRequest struct {
	Name                             string `json:"name,omitempty"`
	GCMKey                           string `json:"gcm_key,omitempty"`
	ChromeKey                        string `json:"chrome_key,omitempty"`
	ChromeWebKey                     string `json:"chrome_web_key,omitempty"`
	ChromeWebOrigin                  string `json:"chrome_web_origin,omitempty"`
	ChromeWebGCMSenderID             string `json:"chrome_web_gcm_sender_id,omitempty"`
	ChromeWebDefaultNotificationIcon string `json:"chrome_web_default_notification_icon,omitempty"`
	ChromeWebSubDomain               string `json:"chrome_web_sub_domain,omitempty"`
	APNSEnv                          string `json:"apns_env,omitempty"`
	APNSP12                          string `json:"apns_p12,omitempty"`
	APNSP12Password                  string `json:"apns_p12_password,omitempty"`
	SafariAPNSP12                    string `json:"safari_apns_p12,omitempty"`
	SafariAPNSP12Password            string `json:"safari_apns_p12_password,omitempty"`
	SafariSiteOrigin                 string `json:"safari_site_origin,omitempty"`
	SafariIcon1616                   string `json:"safari_icon_16_16,omitempty"`
	SafariIcon3232                   string `json:"safari_icon_32_32,omitempty"`
	SafariIcon6464                   string `json:"safari_icon_64_64,omitempty"`
	SafariIcon128128                 string `json:"safari_icon_128_128,omitempty"`
	SafariIcon256256                 string `json:"safari_icon_256_256,omitempty"`
	SiteName                         string `json:"site_name,omitempty"`
}

AppRequest represents a request to create/update an app.

type AppsService

type AppsService struct {
	// contains filtered or unexported fields
}

AppsService handles communication with the app related methods of the OneSignal API.

func (*AppsService) Create

func (s *AppsService) Create(opt *AppRequest) (*App, *http.Response, error)

Create an app.

OneSignal API docs: https://documentation.onesignal.com/docs/apps-create-an-app

func (*AppsService) Get

func (s *AppsService) Get(appID string) (*App, *http.Response, error)

Get a single app.

OneSignal API docs: https://documentation.onesignal.com/docs/appsid

func (*AppsService) List

func (s *AppsService) List() ([]App, *http.Response, error)

List the apps.

OneSignal API docs: https://documentation.onesignal.com/docs/apps-view-apps

func (*AppsService) Update

func (s *AppsService) Update(appID string, opt *AppRequest) (*App, *http.Response, error)

Update an app.

OneSignal API docs: https://documentation.onesignal.com/docs/appsid-update-an-app

type AuthKeyType

type AuthKeyType uint

AuthKeyType specifies the token used to authentify the requests

const (
	APP AuthKeyType = iota
	USER
)

type Client

type Client struct {
	BaseURL *url.URL
	AppKey  string
	UserKey string
	Client  *http.Client

	Apps          *AppsService
	Players       *PlayersService
	Notifications *NotificationsService
}

A Client manages communication with the OneSignal API.

func NewClient

func NewClient(httpClient *http.Client) *Client

NewClient returns a new OneSignal API client.

func (*Client) Do

func (c *Client) Do(r *http.Request, v interface{}) (*http.Response, error)

Do sends an API request and returns the API response. The API response is JSON decoded and stored in the value pointed to by v, or returned as an error if an API error has occurred.

func (*Client) NewRequest

func (c *Client) NewRequest(method, path string, body interface{}, authKeyType AuthKeyType) (*http.Request, error)

NewRequest creates an API request. path is a relative URL, like "/apps". The value pointed to by body is JSON encoded and included as the request body. The AuthKeyType will determine which authorization token (APP or USER) is used for the request.

type ErrorResponse

type ErrorResponse struct {
	Messages []string `json:"errors"`
}

ErrorResponse reports one or more errors caused by an API request.

func (*ErrorResponse) Error

func (e *ErrorResponse) Error() string

type Notification

type Notification struct {
	ID         string            `json:"id"`
	Successful int               `json:"successful"`
	Failed     int               `json:"failed"`
	Converted  int               `json:"converted"`
	Remaining  int               `json:"remaining"`
	QueuedAt   int               `json:"queued_at"`
	SendAfter  int               `json:"send_after"`
	URL        string            `json:"url"`
	Data       interface{}       `json:"data"`
	Canceled   bool              `json:"canceled"`
	Headings   map[string]string `json:"headings"`
	Contents   map[string]string `json:"contents"`
}

Notification represents a OneSignal notification.

type NotificationCreateResponse

type NotificationCreateResponse struct {
	ID         string      `json:"id"`
	Recipients int         `json:"recipients"`
	Errors     interface{} `json:"errors"`
}

NotificationCreateResponse wraps the standard http.Response for the NotificationsService.Create method

type NotificationDeleteOptions

type NotificationDeleteOptions struct {
	AppID string `json:"app_id"`
}

NotificationDeleteOptions specifies the parameters to the NotificationsService.Delete method

type NotificationGetOptions

type NotificationGetOptions struct {
	AppID string `json:"app_id"`
}

NotificationUpdateOptions specifies the parameters to the NotificationsService.Get method

type NotificationListOptions

type NotificationListOptions struct {
	AppID  string `json:"app_id"`
	Limit  int    `json:"limit"`
	Offset int    `json:"offset"`
}

NotificationListOptions specifies the parameters to the NotificationsService.List method

type NotificationListResponse

type NotificationListResponse struct {
	TotalCount    int `json:"total_count"`
	Offset        int `json:"offset"`
	Limit         int `json:"limit"`
	Notifications []Notification
}

NotificationListResponse wraps the standard http.Response for the NotificationsService.List method

type NotificationRequest

type NotificationRequest struct {
	AppID                  string            `json:"app_id"`
	Contents               map[string]string `json:"contents,omitempty"`
	Subtitle               map[string]string `json:"subtitle,omitempty"`
	Headings               map[string]string `json:"headings,omitempty"`
	IsIOS                  bool              `json:"isIos,omitempty"`
	IsAndroid              bool              `json:"isAndroid,omitempty"`
	IsWP                   bool              `json:"isWP,omitempty"`
	IsADM                  bool              `json:"isAdm,omitempty"`
	IsChrome               bool              `json:"isChrome,omitempty"`
	IsChromeWeb            bool              `json:"isChromeWeb,omitempty"`
	IsSafari               bool              `json:"isSafari,omitempty"`
	IsAnyWeb               bool              `json:"isAnyWeb,omitempty"`
	IncludedSegments       []string          `json:"included_segments,omitempty"`
	ExcludedSegments       []string          `json:"excluded_segments,omitempty"`
	IncludePlayerIDs       []string          `json:"include_player_ids,omitempty"`
	IncludeExternalUserIDs []string          `json:"include_external_user_ids,omitempty"`
	IncludeIOSTokens       []string          `json:"include_ios_tokens,omitempty"`
	IncludeAndroidRegIDs   []string          `json:"include_android_reg_ids,omitempty"`
	IncludeWPURIs          []string          `json:"include_wp_uris,omitempty"`
	IncludeWPWNSURIs       []string          `json:"include_wp_wns_uris,omitempty"`
	IncludeAmazonRegIDs    []string          `json:"include_amazon_reg_ids,omitempty"`
	IncludeChromeRegIDs    []string          `json:"include_chrome_reg_ids,omitempty"`
	IncludeChromeWebRegIDs []string          `json:"include_chrome_web_reg_ids,omitempty"`
	AppIDs                 []string          `json:"app_ids,omitempty"`
	Tags                   interface{}       `json:"tags,omitempty"`
	IOSBadgeType           string            `json:"ios_badgeType,omitempty"`
	IOSBadgeCount          int               `json:"ios_badgeCount,omitempty"`
	IOSSound               string            `json:"ios_sound,omitempty"`
	IOSAttachments         map[string]string `json:"ios_attachments,omitempty"`
	IOSCategory            string            `json:"ios_category,omitempty"`
	AndroidSound           string            `json:"android_sound,omitempty"`
	ADMSound               string            `json:"adm_sound,omitempty"`
	WPSound                string            `json:"wp_sound,omitempty"`
	WPWNSSound             string            `json:"wp_wns_sound,omitempty"`
	Data                   interface{}       `json:"data,omitempty"`
	Buttons                interface{}       `json:"buttons,omitempty"`
	SmallIcon              string            `json:"small_icon,omitempty"`
	LargeIcon              string            `json:"large_icon,omitempty"`
	BigPicture             string            `json:"big_picture,omitempty"`
	ADMSmallIcon           string            `json:"adm_small_icon,omitempty"`
	ADMLargeIcon           string            `json:"adm_large_icon,omitempty"`
	ADMBigPicture          string            `json:"adm_big_picture,omitempty"`
	ChromeIcon             string            `json:"chrome_icon,omitempty"`
	ChromeBigPicture       string            `json:"chrome_big_picture,omitempty"`
	ChromeWebIcon          string            `json:"chrome_web_icon,omitempty"`
	FirefoxIcon            string            `json:"firefox_icon,omitempty"`
	URL                    string            `json:"url,omitempty"`
	SendAfter              string            `json:"send_after,omitempty"`
	DelayedOption          string            `json:"delayed_option,omitempty"`
	DeliveryTimeOfDay      string            `json:"delivery_time_of_day,omitempty"`
	TTL                    int               `json:"ttl,omitempty"`
	Priority               int               `json:"priority,omitempty"`
	AndroidLEDColor        string            `json:"android_led_color,omitempty"`
	AndroidAccentColor     string            `json:"android_accent_color,omitempty"`
	AndroidVisibility      int               `json:"android_visibility,omitempty"`
	ContentAvailable       bool              `json:"content_available,omitempty"`
	AndroidBackgroundData  bool              `json:"android_background_data,omitempty"`
	AmazonBackgroundData   bool              `json:"amazon_background_data,omitempty"`
	TemplateID             string            `json:"template_id,omitempty"`
	AndroidGroup           string            `json:"android_group,omitempty"`
	AndroidGroupMessage    interface{}       `json:"android_group_message,omitempty"`
	AndroidChannelID       string            `json:"android_channel_id,omitempty"`
	ThreadID               string            `json:"thread_id,omitempty"`
	SummaryArg             string            `json:"summary_arg,omitempty"`
	SummaryArgCount        int               `json:"summary_arg_count,omitempty"`
	ADMGroup               string            `json:"adm_group,omitempty"`
	ADMGroupMessage        interface{}       `json:"adm_group_message,omitempty"`
	Filters                interface{}       `json:"filters,omitempty"`
}

NotificationRequest represents a request to create a notification. https://documentation.onesignal.com/reference#create-notification

type NotificationUpdateOptions

type NotificationUpdateOptions struct {
	AppID  string `json:"app_id"`
	Opened bool   `json:"opened"`
}

NotificationUpdateOptions specifies the parameters to the NotificationsService.Update method

type NotificationsService

type NotificationsService struct {
	// contains filtered or unexported fields
}

NotificationsService handles communication with the notification related methods of the OneSignal API.

func (*NotificationsService) Create

Create a notification.

OneSignal API docs: https://documentation.onesignal.com/docs/notifications-create-notification

func (*NotificationsService) Delete

Delete a notification.

OneSignal API docs: https://documentation.onesignal.com/docs/notificationsid-cancel-notification

func (*NotificationsService) Get

Get a single notification.

OneSignal API docs: https://documentation.onesignal.com/docs/notificationsid-view-notification

func (*NotificationsService) List

List the notifications.

OneSignal API docs: https://documentation.onesignal.com/docs/notifications-view-notifications

func (*NotificationsService) Update

Update a notification.

OneSignal API docs: https://documentation.onesignal.com/docs/notificationsid-track-open

type Player

type Player struct {
	ID                string            `json:"id"`
	Playtime          int               `json:"playtime"`
	SDK               string            `json:"sdk"`
	Identifier        string            `json:"identifier"`
	SessionCount      int               `json:"session_count"`
	Language          string            `json:"language"`
	Timezone          int               `json:"timezone"`
	GameVersion       string            `json:"game_version"`
	DeviceOS          string            `json:"device_os"`
	DeviceType        int               `json:"device_type"`
	DeviceModel       string            `json:"device_model"`
	AdID              string            `json:"ad_id"`
	Tags              map[string]string `json:"tags"`
	LastActive        int               `json:"last_active"`
	AmountSpent       float32           `json:"amount_spent"`
	CreatedAt         int               `json:"created_at"`
	InvalidIdentifier bool              `json:"invalid_identifier"`
	BadgeCount        int               `json:"badge_count"`
}

Player represents a OneSignal player.

type PlayerCSVExportOptions

type PlayerCSVExportOptions struct {
	AppID string `json:"app_id"`
}

PlayerCSVExportOptions specifies the parameters to the PlayersService.CSVExport method

type PlayerCSVExportResponse

type PlayerCSVExportResponse struct {
	CSVFileURL string `json:"csv_file_url"`
}

PlayerCSVExportResponse wraps the standard http.Response for the PlayersService.CSVExport method

type PlayerCreateResponse

type PlayerCreateResponse struct {
	Success bool   `json:"success"`
	ID      string `json:"id"`
}

PlayerCreateResponse wraps the standard http.Response for the PlayersService.Create method

type PlayerListOptions

type PlayerListOptions struct {
	AppID  string `json:"app_id"`
	Limit  int    `json:"limit"`
	Offset int    `json:"offset"`
}

PlayerListOptions specifies the parameters to the PlayersService.List method

type PlayerListResponse

type PlayerListResponse struct {
	TotalCount int `json:"total_count"`
	Offset     int `json:"offset"`
	Limit      int `json:"limit"`
	Players    []Player
}

PlayerListResponse wraps the standard http.Response for the PlayersService.List method

type PlayerOnFocusOptions

type PlayerOnFocusOptions struct {
	State      string `json:"state"`
	ActiveTime int    `json:"active_time"`
}

PlayerOnFocusOptions specifies the parameters to the PlayersService.OnFocus method

type PlayerOnPurchaseOptions

type PlayerOnPurchaseOptions struct {
	Purchases []Purchase `json:"purchases"`
	Existing  bool       `json:"existing,omitempty"`
}

PlayerOnPurchaseOptions specifies the parameters to the PlayersService.OnPurchase method

type PlayerOnSessionOptions

type PlayerOnSessionOptions struct {
	Identifier  string            `json:"identifier,omitempty"`
	Language    string            `json:"language,omitempty"`
	Timezone    int               `json:"timezone,omitempty"`
	GameVersion string            `json:"game_version,omitempty"`
	DeviceOS    string            `json:"device_os,omitempty"`
	AdID        string            `json:"ad_id,omitempty"`
	SDK         string            `json:"sdk,omitempty"`
	Tags        map[string]string `json:"tags,omitempty"`
}

PlayerOnSessionOptions specifies the parameters to the PlayersService.OnSession method

type PlayerRequest

type PlayerRequest struct {
	AppID             string            `json:"app_id"`
	DeviceType        int               `json:"device_type"`
	Identifier        string            `json:"identifier,omitempty"`
	Language          string            `json:"language,omitempty"`
	Timezone          int               `json:"timezone,omitempty"`
	GameVersion       string            `json:"game_version,omitempty"`
	DeviceOS          string            `json:"device_os,omitempty"`
	DeviceModel       string            `json:"device_model,omitempty"`
	AdID              string            `json:"ad_id,omitempty"`
	SDK               string            `json:"sdk,omitempty"`
	SessionCount      int               `json:"session_count,omitempty"`
	Tags              map[string]string `json:"tags,omitempty"`
	AmountSpent       float32           `json:"amount_spent,omitempty"`
	CreatedAt         int               `json:"created_at,omitempty"`
	Playtime          int               `json:"playtime,omitempty"`
	BadgeCount        int               `json:"badge_count,omitempty"`
	LastActive        int               `json:"last_active,omitempty"`
	TestType          int               `json:"test_type,omitempty"`
	NotificationTypes string            `json:"notification_types,omitempty"`
}

PlayerRequest represents a request to create/update a player.

type PlayersService

type PlayersService struct {
	// contains filtered or unexported fields
}

PlayersService handles communication with the player related methods of the OneSignal API.

func (*PlayersService) CSVExport

Generate a link to download a CSV list of all the players.

OneSignal API docs: https://documentation.onesignal.com/docs/players_csv_export

func (*PlayersService) Create

Create a player.

OneSignal API docs: https://documentation.onesignal.com/docs/players-add-a-device

func (*PlayersService) Get

func (s *PlayersService) Get(playerID string) (*Player, *http.Response, error)

Get a single player.

OneSignal API docs: https://documentation.onesignal.com/docs/playersid

func (*PlayersService) List

List the players.

OneSignal API docs: https://documentation.onesignal.com/docs/players-view-devices

func (*PlayersService) OnFocus

func (s *PlayersService) OnFocus(playerID string, opt *PlayerOnFocusOptions) (*SuccessResponse, *http.Response, error)

Increment the total session length for a player.

OneSignal API docs: https://documentation.onesignal.com/docs/playersidon_focus

func (*PlayersService) OnPurchase

func (s *PlayersService) OnPurchase(playerID string, opt *PlayerOnPurchaseOptions) (*SuccessResponse, *http.Response, error)

Create a new purchase for a player.

OneSignal API docs: https://documentation.onesignal.com/docs/on_purchase

func (*PlayersService) OnSession

func (s *PlayersService) OnSession(playerID string, opt *PlayerOnSessionOptions) (*SuccessResponse, *http.Response, error)

Create a new session for a player.

OneSignal API docs: https://documentation.onesignal.com/docs/playersidon_session

func (*PlayersService) Update

func (s *PlayersService) Update(playerID string, player *PlayerRequest) (*SuccessResponse, *http.Response, error)

Update a player.

OneSignal API docs: https://documentation.onesignal.com/docs/playersid-1

type Purchase

type Purchase struct {
	SKU    string  `json:"sku"`
	Amount float32 `json:"amount"`
	ISO    string  `json:"iso"`
}

Purchase represents a purchase in the options of the PlayersService.OnPurchase method

type SuccessResponse

type SuccessResponse struct {
	Success bool `json:"success"`
}

SuccessResponse wraps the standard http.Response for several API methods that just return a Success flag.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL