Python library for the Stripe API.

Overview

Stripe Python Library

Build Status Coverage Status

The Stripe Python library provides convenient access to the Stripe API from applications written in the Python language. It includes a pre-defined set of classes for API resources that initialize themselves dynamically from API responses which makes it compatible with a wide range of versions of the Stripe API.

Documentation

See the Python API docs.

See video demonstrations covering how to use the library.

Installation

You don't need this source code unless you want to modify the package. If you just want to use the package, just run:

pip install --upgrade stripe

Install from source with:

python setup.py install

Requirements

  • Python 2.7+ or Python 3.4+ (PyPy supported)

Usage

The library needs to be configured with your account's secret key which is available in your Stripe Dashboard. Set stripe.api_key to its value:

import stripe
stripe.api_key = "sk_test_..."

# list customers
customers = stripe.Customer.list()

# print the first customer's email
print(customers.data[0].email)

# retrieve specific Customer
customer = stripe.Customer.retrieve("cus_123456789")

# print that customer's email
print(customer.email)

Handling exceptions

Unsuccessful requests raise exceptions. The class of the exception will reflect the sort of error that occurred. Please see the Api Reference for a description of the error classes you should handle, and for information on how to inspect these errors.

Per-request Configuration

Configure individual requests with keyword arguments. For example, you can make requests with a specific Stripe Version or as a connected account:

import stripe

# list customers
stripe.Customer.list(
    api_key="sk_test_...",
    stripe_account="acct_...",
    stripe_version="2019-02-19"
)

# retrieve single customer
stripe.Customer.retrieve(
    "cus_123456789",
    api_key="sk_test_...",
    stripe_account="acct_...",
    stripe_version="2019-02-19"
)

Configuring a Client

The library can be configured to use urlfetch, requests, pycurl, or urllib2 with stripe.default_http_client:

client = stripe.http_client.UrlFetchClient()
client = stripe.http_client.RequestsClient()
client = stripe.http_client.PycurlClient()
client = stripe.http_client.Urllib2Client()
stripe.default_http_client = client

Without a configured client, by default the library will attempt to load libraries in the order above (i.e. urlfetch is preferred with urllib2 used as a last resort). We usually recommend that people use requests.

Configuring a Proxy

A proxy can be configured with stripe.proxy:

stripe.proxy = "https://user:[email protected]:1234"

Configuring Automatic Retries

You can enable automatic retries on requests that fail due to a transient problem by configuring the maximum number of retries:

stripe.max_network_retries = 2

Various errors can trigger a retry, like a connection error or a timeout, and also certain API responses like HTTP status 409 Conflict.

Idempotency keys are automatically generated and added to requests, when not given, to guarantee that retries are safe.

Logging

The library can be configured to emit logging that will give you better insight into what it's doing. The info logging level is usually most appropriate for production use, but debug is also available for more verbosity.

There are a few options for enabling it:

  1. Set the environment variable STRIPE_LOG to the value debug or info

    $ export STRIPE_LOG=debug
  2. Set stripe.log:

    import stripe
    stripe.log = 'debug'
  3. Enable it through Python's logging module:

    import logging
    logging.basicConfig()
    logging.getLogger('stripe').setLevel(logging.DEBUG)

Writing a Plugin

If you're writing a plugin that uses the library, we'd appreciate it if you identified using stripe.set_app_info():

stripe.set_app_info("MyAwesomePlugin", version="1.2.34", url="https://myawesomeplugin.info")

This information is passed along when the library makes calls to the Stripe API.

Request latency telemetry

By default, the library sends request latency telemetry to Stripe. These numbers help Stripe improve the overall latency of its API for all users.

You can disable this behavior if you prefer:

stripe.enable_telemetry = False

Development

The test suite depends on stripe-mock, so make sure to fetch and run it from a background terminal (stripe-mock's README also contains instructions for installing via Homebrew and other methods):

go get -u github.com/stripe/stripe-mock
stripe-mock

Run the following command to set up the development virtualenv:

make

Run all tests on all supported Python versions:

make test

Run all tests for a specific Python version (modify -e according to your Python target):

TOX_ARGS="-e py37" make test

Run all tests in a single file:

TOX_ARGS="-e py37 -- tests/api_resources/abstract/test_updateable_api_resource.py" make test

Run a single test suite:

TOX_ARGS="-e py37 -- tests/api_resources/abstract/test_updateable_api_resource.py::TestUpdateableAPIResource" make test

Run a single test:

TOX_ARGS="-e py37 -- tests/api_resources/abstract/test_updateable_api_resource.py::TestUpdateableAPIResource::test_save" make test

Run the linter with:

make lint

The library uses Black for code formatting. Code must be formatted with Black before PRs are submitted, otherwise CI will fail. Run the formatter with:

make fmt
Comments
  • Allow access to request metadata on success

    Allow access to request metadata on success

    Hey @ob-stripe this is my first stab at getting response headers out of the python bindings.

    I'm trying to follow the same pattern by including a response resource to the returned API models.

    However one tricky part is understanding where the best spot is to place an optional flag to include the response field on returned API resources. Each API request method contains a paramsparameter that directly maps to the API's URL parameters. Placing some kind of include_response flag here would stick out since it won't be going to the API.

    Another thought was using a static variable somewhere and checking that variable within the api_requestor to include the response or not.

    Do you have any opinions here?

    opened by sedouard 27
  • UPDATE: Stripe API proxy support for requests, pycurl, and urllib2 clients

    UPDATE: Stripe API proxy support for requests, pycurl, and urllib2 clients

    In complex enterprise environment, different proxies may be used for communication across the many enterprise network zones, the Internet. Obviously, the HTTP_PROXY and HTTPS_PROXY environment variables are more trouble than help there.

    A clean solution would be introducing API level proxy support that limits the proxy scope to just stripe communication. Everybody else would remain unaffected and could continue using either direct or own, different HTTP proxy configuration.

    This pull request introduces the proxy API support described. The new proxy-example.py file demonstrates the proxy API usage.

    Please consider prompt review of this pull request. Not having the proxy support will affect our project with an externally set, beyond our control hard deadline.

    Happy to address any questions or concerns.

    Thank you!

    approved 
    opened by krassif 24
  • Add support for Google App Engine dev server

    Add support for Google App Engine dev server

    Summary

    Currently the stripe library is not compatible with the App Engine dev server, this fixes that by disabling the ssl revoked cert check when running on the dev app server.

    More detail

    Google App Engine blocks access to many C modules including the socket module. It provides its own implementation but this causes a TypeError when used with the ssl C module.

    This PR skips the ssl preflight check when a TypeError occurs on the App Engine server, this doesn't add much risk as the attacker would have to be in control of the connection between the user and stripe and also have a copy of the pre-heartbleed ssl private key. In any case the check can be bypassed since connections aren't reused and the check is only done once for the lifetime of an instance so an attacker would simply trigger a stripe request on the target website (buy something with a dummy card) to get the check out the way and then start the MITM attack then trigger another stripe transaction and get the secret key.

    Why catch the exception rather than detect the environment?

    If a fix for the underlying issue with the App Engine dev server gets released then the check will work again.

    Feedback

    Not sure whether it is appropriate to include a warning here? If so, what should it say?

    opened by danielchatfield 18
  • Better support for uploading in-memory images

    Better support for uploading in-memory images

    A fairly common use case for file uploads is to upload an image to Stripe that was just uploaded to the server, or to retrieve an image from a URL, then upload it to Stripe. As it stands, the file uploader seems to expect to be given a file stored on disk, which isn't really necessary. More specifically, the file uploader wants something that has a .read method, and a .name method.

    Right now, if I take a StringIO (which supports .read), then monkey-patch it to have .name="foo", this seems to upload fine, and I more or less get the thing I want. This is a bit gross, though. Ideally, we wouldn't require a file name for the file at all, since this doesn't appear to be getting used in any meaningful way. (The upload response or anything else I can find doesn't seem to make reference to the filename.)

    Though it doesn't seem like uploads.stripe.com actually does anything with the file name, it does get unhappy if the parameter is omitted or left blank. As far as I can tell, if I patch stripe-python to just pass a hard-coded dummy value as the file name, this works fine. This is clearly a hack, though. In an ideal world, uploadsrv wouldn't look for a filename at all, though I don't really know if that would be a simple change or not.

    Thoughts on whether this is something we'd want to support, and if so, what the cleanest way of doing this is?

    future 
    opened by praboud 16
  • Try to reuse the HttpClient between requests by default

    Try to reuse the HttpClient between requests by default

    Previously, if the user has not set stripe.default_http_client, a new client would be created for every request. This commit changes the APIRequestor to populate stripe.default_http_client if it had not been set by the user, so the client can be reused between requests.

    r? @brandur-stripe @ob-stripe cc @stripe/api-libraries

    opened by jameshageman-stripe 15
  • Fix ssl import error in GAE

    Fix ssl import error in GAE

    This avoids an ImportError when loading the SSL library in a Google App Engine dev environment. For more details, see: https://code.google.com/p/googleappengine/issues/detail?id=9246

    This PR is a followup from an internal ticket. I'll merge once the reporter has confirmed that this fixes the issue in his environment.

    opened by metcalf 15
  • Implement retry mechanism when using requests

    Implement retry mechanism when using requests

    This PR implements a retry mechanism if any request would fail when using requests. It closes #464.

    More detailed documentation of Retry can be found in the urllib3 documentation

    • Total: The amount of total retries
    • backoff_factor: it will sleep for: {backoff factor} * (2 ^ ({number of total retries} - 1)) between retries
    • status: How many times to retry on bad status codes. The ones on status_forcelist
    • status_forcelist: Bad status codes which it will retry on.
    opened by jonathan-s 14
  • Install started failing for users of older pip

    Install started failing for users of older pip

    @brandur-stripe @ob-stripe Requests 2.14.1 just released and now requires pip >= 8.1.2 and a newish version of setuptools https://github.com/kennethreitz/requests/issues/4006

    As of today, stripe-python will fail to install for users of older packaging infrastructure, including Travis. https://travis-ci.org/stripe/stripe-python/jobs/230553497#L497 https://github.com/kennethreitz/requests/pull/4007#issuecomment-300364756

    We should deploy an emergency release limiting requests to version 2.13.0 and documentation should be added detailing that in the next major release there will be a minimum required version of pip.

    opened by ofek 14
  • Add Stripe client telemetry to request headers

    Add Stripe client telemetry to request headers

    Follows https://github.com/stripe/stripe-ruby/pull/696 and https://github.com/stripe/stripe-php/pull/549 in adding telemetry metadata to request headers.

    The telemetry is disabled by default, and can be enabled like so:

    stripe.enable_telemetry = True
    
    approved 
    opened by jameshageman-stripe 12
  • Add `modify` class method for updateable resources

    Add `modify` class method for updateable resources

    I'd much rather call this method update, but we can't use that name because StripeObject already has an update method, and I'd rather not make this a breaking change. Note that this PR is not ready merge. There are a few resources that are going to need a custom modify method due to URL format.

    approved 
    opened by kyleconroy 12
  • Stripe Python API library broken for use on Google AppEngine

    Stripe Python API library broken for use on Google AppEngine

    I've just updated Stripe API library to the latest version and it stopped working on Google AppEngine due to fact that GAE is blocking imports of some packages such as sockets and SSL.

    ERROR    2014-05-10 09:55:16,576 base.py:215] Internal Server Error: /api/billing/subscribe_to_paid_plan/stripe
        Traceback (most recent call last):
    ...
         File "/src/classes/billing/api_views.py", line 3, in <module>
            import stripe
          File "/src/stripe/__init__.py", line 16, in <module>
            from stripe.resource import (  # noqa
          File "/src/stripe/resource.py", line 5, in <module>
            from stripe import api_requestor, error, util
          File "/src/stripe/api_requestor.py", line 5, in <module>
            import ssl
          File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py", line 60, in <module>
            import _ssl             # if we can't import it, let the error propagate
          File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/devappserver2/python/sandbox.py", line 852, in load_module
            raise ImportError('No module named %s' % fullname)
        ImportError: No module named _ssl
    

    Are there any chances to make it working on Google AppEngine?

    I believe the old lib was just fine. It would be pity if we would be forced to use some other payment system as we like Stripe very much!

    opened by trakhimenok 12
  • API Updates

    API Updates

    Codegen for openapi v216. cc @stripe/api-libraries

    Changelog

    • Remove support for resources Order and Sku
    • Remove support for cancel, create, list_line_items, list, modify, reopen, retrieve, and submit methods on resource Order
    • Remove support for create, delete, list, modify, and retrieve methods on resource Sku
    opened by richardm-stripe 0
  • stripe api with `requests` leaks socket file descriptors via unclosed Session

    stripe api with `requests` leaks socket file descriptors via unclosed Session

    Describe the bug

    the http request client is assigned to a global variable here: https://github.com/stripe/stripe-python/blob/1ae42227d9df745420c1a3db11893589d91ba83e/stripe/api_requestor.py#L103-L105

    requests client is defined here: https://github.com/stripe/stripe-python/blob/1ae42227d9df745420c1a3db11893589d91ba83e/stripe/http_client.py#L287

    the Session is assigned here: https://github.com/stripe/stripe-python/blob/1ae42227d9df745420c1a3db11893589d91ba83e/stripe/http_client.py#L318-L319

    this Session is never closed leading to file descriptor leak and a ResourceWarning -- the correct usage of a Session is to either utilize the with statement or explicitly .close() it

    To Reproduce

    the simplest reproduction I can come up with is this one liner:

    $ python3  -Wonce -c $'import stripe; stripe.api_key="placeholder"; import contextlib\nwith contextlib.suppress(Exception):\n stripe.Account.list()'
    sys:1: ResourceWarning: unclosed <ssl.SSLSocket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('10.0.2.15', 44434), raddr=('34.200.27.109', 443)>
    

    the ResourceWarning there is coming from the teardown of that Session object I mentioned above -- it's an unclosed connection to the stripe api:

    $ nslookup 34.200.27.109
    109.27.200.34.in-addr.arpa	name = api-34-200-27-109.stripe.com.
    
    Authoritative answers can be found from:
    
    

    Expected behavior

    utilization of the stripe api should not lead to ResourceWarnings

    Code snippets

    above
    

    OS

    any, though I'm on linux

    Language version

    any, though I'm using 3.10.4

    Library version

    4.1.0

    API version

    N/A

    Additional context

    No response

    bug future 
    opened by asottile-sentry 7
  • For webhooks, `webhook.request` is both a method and a data attribute

    For webhooks, `webhook.request` is both a method and a data attribute

    Describe the bug

    Incoming webhook events have a request data attribute, but the event instance already has a request bound method, so we end up with a bit of a conflict. The data attribute can still be accessed with event["request"] but it feels weird to need to do that for just that one data attribute and then use dot syntax for everything else.

    >>> event = stripe.Webhook.construct_event(...)
    
    >>> event.request
    <bound method StripeObject.request of <Event event id=<id_omitted> at 0x1035bb450> JSON: { ...
    
    >>> event["request"]
    <StripeObject id=<id_omitted> at 0x102e95810> JSON: {
      "id": "<id_omitted>",
      "idempotency_key": "<idempotency_key_omitted>"
    }
    

    event.request and event["request"] both returning different things is rather confusing, and it took me quite a while to figure out what was going on.

    To Reproduce

    1. Construct a webhook event.
    2. Access event.request.
    3. Access event["request"].
    4. Notice that they are different.

    I would probably consider this less of a "bug" and more of an oversight.

    Expected behavior

    The event.request method should probably be something like event._request so it doesn't conflict with the incoming data. That way I can call event.request and actually get the attribute from the body of the webhook as expected.

    Code snippets

    No response

    OS

    macOS

    Language version

    Python 3.9.10

    Library version

    stripe-python v2.76.0

    API version

    2020-08-27

    Additional context

    No response

    bug future 
    opened by AaronBeaudoin 3
  • Setting a List Field to [] When Modifying a Resource Doesn't Actually Empty The List Field

    Setting a List Field to [] When Modifying a Resource Doesn't Actually Empty The List Field

    Describe the bug

    When trying to clear out the list of previously set blocked_categories on a cardholder, calling

    stripe.issuing.Cardholder.modify(
        "ich_...",
        spending_controls={'blocked_categories': []},
        stripe_account="acct_...",
    )
    

    returns successfully but doesn't clear out the blocked_categories on the cardholder and returns a cardholder instance with the previous blocked_categories list still set.

    Instead, it is necessary to replace [] with "":

    stripe.issuing.Cardholder.modify(
        "ich_...",
        spending_controls={'blocked_categories': ""},
        stripe_account="acct_...",
    )
    

    and that successfully clears the list of blocked_categories—however, there is no mention of the need to make this distinction when calling stripe.issuing.Cardholder.modify or any other method in the Stripe API docs or this library's docs and setting a list to empty by setting its value to "" is not valid Python syntax.

    To Reproduce

    1. create a stripe connect account via:
    stripe.Account.create(
        type="custom",
        country="US",
        email="[email protected]",
        requested_capabilities=["transfers", "card_payments", "card_issuing"],
    )
    
    1. complete any requested test KYB information to ensure the account is fully verified and approved
    2. create a cardholder via:
    stripe.issuing.Cardholder.create(
        name="Jane Doe",
        email="[email protected]",
        status="active",
        type="individual",
        billing={
            "name": "Jane Doe",
            "address": {
                "line1": "117 West St",
                "line2": None,
                "city": "New York",
                "state": "NY",
                "country": "US",
                "postal_code": "10006",
            },
        },
        spending_controls={'blocked_categories': ['floor_covering_stores']},
        stripe_account="acct_...",  # id of the account created above
    )
    
    1. attempt to update the cardholder via:
    stripe.issuing.Cardholder.modify(
        "ich_...",  # id of the cardholder created above
        spending_controls={'blocked_categories': []},
        stripe_account="acct_...",  # id of the account created above
    )
    

    Expected behavior

    Setting a list to [] should set that list to empty. It is not intuitive or valid Python syntax to set a list to empty by setting its value to "".

    Code snippets

    See code snippets in the "Describe the bug" and "To Reproduce" sections

    OS

    macOS

    Language version

    Python 3.10.2

    Library version

    stripe-python v2.67.0

    API version

    2019-10-17

    Additional context

    No response

    bug 
    opened by jake-kent 1
  • JSON log formatting

    JSON log formatting

    Hello,

    It would be great to allow users to format logs in json format instead of the hardcoded logfmt format in the library. For those looking to make this work, this is how we did it:

    # strip_log_formatter.py
    import datetime
    import json
    
    from pythonjsonlogger import jsonlogger
    
    
    class StripeJsonLogFormatter(jsonlogger.JsonFormatter):  # pragma: no cover
        def add_fields(self, log_record, record, message_dict):
            """
            This method allows us to inject custom data into resulting log messages
            """
            for field in self._required_fields:
                log_record[field] = record.__dict__.get(field)
            log_record.update(message_dict)
    
            # Add timestamp and application name if not present
            if 'timestamp' not in log_record:
                now = datetime.datetime.utcnow()
                log_record['timestamp'] = now.isoformat()
            if 'application' not in log_record:
                log_record['application'] = 'myapp'
    
            if 'level' not in log_record:
                log_record['level'] = record.levelname
    
            jsonlogger.merge_record_extra(record, log_record, reserved=self._skip_fields)
    

    Reference this class from stripe_log_formatter.py in log ini configuration file as follows:

    [loggers]
    keys=stripe
    
    [handlers]
    keys=stripe_file
    
    [formatters]
    keys=stripe_json
    
    [logger_stripe]
    level=INFO
    handlers=stripe_file
    qualname=stripe
    propagate=0
    
    [handler_stripe_file]
    class=logging.handlers.WatchedFileHandler
    formatter=stripe_json
    args=('/var/log/myapp/stripe.json',)
    
    [formatter_stripe_json]
    class=app.stripe_log_formatter.StripeJsonLogFormatter
    

    And then at import time, monkey patch stripe library:

    # Monkey patch Stripe logfmt formatter
    # Watch for this code if it ever changes, things will break:
    # https://github.com/stripe/stripe-python/blob/v2.67.0/stripe/util.py#L82
    
    old_log_fmt = stripe.util.logfmt
    
    def new_logfmt(props):
        return OrderedDict(sorted(props.items(), key=lambda x: x[0]))
    
    stripe.util.logfmt = new_logfmt
    

    Any chance we can get an ability to configure our own log formatter?

    opened by neilpanchal 0
Releases(v5.1.0b3)
Docker image for epicseven gvg qq chatbot based on Xunbot

XUN_Langskip XUN 是一个基于 NoneBot 和 酷Q 的功能型QQ机器人,目前提供了音乐点播、音乐推荐、天气查询、RSSHub订阅、使用帮助、识图、识番、搜番、上车、磁力搜索、地震速报、计算、日语词典、翻译、自我检查,权限等级功能,由于是为了完成自己在群里的承诺,一时兴起才做的,所

Xavier Xiong 2 Jun 08, 2022
Create custom Vanity URLs for Discord without 30 boosts

CustomVanity - Made by udp#6666 aka Apolo - OpenSource Custom Discord Vanity Creator How To Use Open CustomVanity.py Write your server invite code Wri

apolo 17 Aug 23, 2022
Torrent-Igruha SDK Python

Простой пример использования библиотеки: Устанавливаем библиотеку python -m

LORD_CODE 2 Jun 25, 2022
Windows版本微信客户端(非网页版)自动化,可实现简单的发送、接收微信消息

wxauto Windows版本微信客户端自动化,可实现简单的发送、接收微信消息

357 Dec 29, 2022
Telegram Link Shortener Bot (With 20 Shorteners)

Telegram ShortenerBot ShortenerBot: 🇬🇧 Telegram Link Shortener Bot (11 + 9 Shorteners) 🇹🇷 Telegram Link Kısaltıcı Bot (11 + 9 Kısaltıcı) All suppo

Hüzünlü Artemis [HuzunluArtemis] 10 May 24, 2022
Discord Unverified Token Gen

Discord-Unverified-Token-Gen This is a token gen that was made in an hour and just generates unverified tokens, most will be locked. Usage: in cmd jus

Aran 2 Oct 23, 2022
fbchat - Facebook Messenger for Python

A powerful and efficient library to interact with Facebook's Messenger, using just your email and password.

1.1k Dec 23, 2022
Wanna play on the Overwatch NA servers?

OverwatchRegionSwapper-NA- Wanna play on the Overwatch NA servers? Use at you own risk. LIST OF IPs EU Netherlands: From: 5.42.168.0 to: 5.42.175.255

1 Jun 08, 2022
Download archived malware from ActiveState's source code mirror

malware-archivist (ma) Tool to aid security researchers in dissecting malware. Often, repository maintainers will remove malicious packages entirely f

ActiveState Software 28 Dec 12, 2022
A Discord Server Cloner With Lot Of New Features.

Technologies Screenshots Table of contents About Installation Links Deployed Features Website Score Contribution Need Help? Instagram Discord About A

NotSakshyam 25 Dec 31, 2022
A python script fetches all your starred repositories from your GitHub account and clones them to your server so you will never lose important resources

A python script fetches all your starred repositories from your GitHub account and clones them to your server so you will never lose important resources

Ringo Hoffmann 27 Oct 01, 2022
Bin Checker with Aiogram, Telegram

Bin Checker with Aiogram, Telegram

JEFF 1 Aug 16, 2022
Example of a discord bot in Python

discordbot.py Example of a discord bot in Python Requirements Python 3.8 or higher Discord Bot Setting Up Clone this repo or download the files Rename

Debert Jamie 1 Oct 23, 2021
A melhor maneira de atender seus clientes no Telegram!

Clientes.Chat Sobre o serviço Configuração Banco de Dados Variáveis de Ambiente Docker Python Heroku Contribuição Sobre o serviço A maneira mais organ

Gabriel R F 10 Oct 12, 2022
WakeNote is a tool that hides notifications from you until you confirm you want to read them, with technology to help prevent the reading of depressing messages first thing in the morning.

By: Seanpm2001, Et; Al. Top README.md Read this article in a different language Sorted by: A-Z Sorting options unavailable ( af Afrikaans Afrikaans |

Sean P. Myrick V19.1.7.2 3 Oct 21, 2022
Music bot because Octave is down and I can : )

Chords On a mission to build the best Discord Music Bot View Demo · Report Bug · Request Feature Table of Contents About The Project Built With Gettin

Aman Prakash Jha 53 Jan 07, 2023
Bearer API client for Python

Bearer Python Bearer Python client Installation pip install bearer Usage Get your Bearer Secret Key and integration id from the Dashboard and use the

Bearer 9 Oct 31, 2022
Google scholar share - Simple python script to pull Google Scholar data from an author's profile

google_scholar_share Simple python script to pull Google Scholar data from an au

Paul Goldsmith-Pinkham 9 Sep 15, 2022
Userbot untuk memutar video dan lagu di vcg/os

Userbot untuk memutar video dan lagu di vcg/os

FJ_GAMING 2 Nov 13, 2021