Skip to content

Commit

Permalink
[Add] 🎉 Python Package
Browse files Browse the repository at this point in the history
  • Loading branch information
Harry-zklcdc committed Mar 11, 2024
1 parent e0d3dfb commit 2af2d25
Show file tree
Hide file tree
Showing 7 changed files with 354 additions and 0 deletions.
148 changes: 148 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
name: Build & Release
on:
push:

jobs:
build_windows:
name: Build Windows Python Whell Package
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 'stable'
check-latest: true

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Set up Python Package
run: pip install wheel setuptools

- name: Build
run: |
go build -ldflags="-s -w" -trimpath -buildmode=c-shared -o ms_auth/ms_auth.dll ./ms_auth/ && python3 setup.py bdist_wheel -p win_amd64
- uses: actions/upload-artifact@v3
with:
name: ms_auth-py3-win_amd64.whl
path: dist/ms_auth-*-win_amd64.whl

build_macos:
name: Build macOS Python Whell Package
runs-on: macos-14
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 'stable'
check-latest: true

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Set up Python Package
run: pip install wheel setuptools

- name: Build
run: |
CGO_ENABLED=1 GOOS=darwin GOARCH=amd64 go build -ldflags="-s -w" -trimpath -buildmode=c-shared -o ms_auth/ms_auth.so ./ms_auth/ && python3 setup.py bdist_wheel -p macosx_x86_64 && \
CGO_ENABLED=1 GOOS=darwin GOARCH=arm64 go build -ldflags="-s -w" -trimpath -buildmode=c-shared -o ms_auth/ms_auth.so ./ms_auth/ && python3 setup.py bdist_wheel -p macosx_arm64
- uses: actions/upload-artifact@v3
with:
name: ms_auth-py3-macosx_x86_64.whl
path: dist/ms_auth-*-macosx_x86_64.whl

- uses: actions/upload-artifact@v3
with:
name: ms_auth-py3-macosx_arm64.whl
path: dist/ms_auth-*-macosx_arm64.whl

build_linux:
name: Build Linux Python Whell Package
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 'stable'
check-latest: true

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Set up CGo
run: |
sudo apt-get update && sudo apt-get install build-essential gcc-aarch64-linux-gnu
- name: Set up Python Package
run: |
pip install wheel setuptools
- name: Build
run: |
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -trimpath -buildmode=c-shared -o ms_auth/ms_auth.so ./ms_auth/ && python3 setup.py bdist_wheel -p linux_x86_64 && \
CGO_ENABLED=1 CC=aarch64-linux-gnu-gcc GOOS=linux GOARCH=arm64 go build -ldflags="-s -w" -trimpath -buildmode=c-shared -o ms_auth/ms_auth.so ./ms_auth/ && python3 setup.py bdist_wheel -p linux_aarch64
- uses: actions/upload-artifact@v3
with:
name: ms_auth-py3-linux_x86_64.whl
path: dist/ms_auth-*-linux_x86_64.whl

- uses: actions/upload-artifact@v3
with:
name: ms_auth-py3-linux_aarch64.whl
path: dist/ms_auth-*-linux_aarch64.whl

release:
name: Release
needs: [build_windows, build_macos, build_linux]
runs-on: ubuntu-latest
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install twine
- name: Download artifact
uses: actions/download-artifact@v3
with:
path: dist

- name: Publish to PyPI
run: |
twine upload --skip-existing dist/*
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}

- name: Create Release and Upload Release Asset
uses: softprops/action-gh-release@v1
with:
files: |
dist/*.whl
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
build/
dist/
ms_auth.egg-info/
6 changes: 6 additions & 0 deletions ms_auth/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
__pycache__

# Golang C Export
*.h
*.dll
*.so
1 change: 1 addition & 0 deletions ms_auth/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .auth import msAuth
92 changes: 92 additions & 0 deletions ms_auth/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
from ctypes import cdll, c_char_p, Structure
import os
import sys

class Auth(Structure):
_fields_ = [
('cookies', c_char_p),
('ctx', c_char_p),
('errStr', c_char_p),
]

current_dir = os.path.dirname(os.path.abspath(__file__))
lib = cdll.LoadLibrary(current_dir + '/ms_auth.dll') if sys.platform == 'win32' else cdll.LoadLibrary(current_dir + '/ms_auth.so')

_auth = lib.auth
_auth.argtypes = [c_char_p, c_char_p, c_char_p]
_auth.restype = Auth

_authEmail = lib.authEmail
_authEmail.argtypes = [c_char_p, c_char_p, c_char_p, c_char_p, c_char_p]
_authEmail.restype = Auth

_authDevice = lib.authDevice
_authDevice.argtypes = [c_char_p, c_char_p, c_char_p, c_char_p]
_authDevice.restype = Auth

class msAuth:
def __init__(self, account, authType, password='') ->None:
self.account = account.encode('utf-8')
self.password = password.encode('utf-8')
self.authType = authType.encode('utf-8')

def auth(self) -> tuple[str, str]:
try:
res = _auth(self.account, self.password, self.authType)
err = res.errStr.decode('utf-8')
if err != '' and err != 'email login need code to continue' and not err.startswith('device login need handler to continue'):
raise Exception(res.errStr.decode('utf-8'))
self.ctx = res.ctx
self.cookies = res.cookies
if err.startswith('device login need handler to continue'):
self.code = err.split(' ')[-1]
return res.cookies.decode('utf-8'), res.errStr.decode('utf-8')
except KeyboardInterrupt:
pass

def authEmail(self, code) -> tuple[str, str]:
try:
res = _authEmail(self.account, code.encode('utf-8'), self.authType, self.ctx, self.cookies)
if res.errStr.decode('utf-8') != '':
raise Exception(res.errStr.decode('utf-8'))
self.cookies = res.cookies
return res.cookies.decode('utf-8'), res.errStr.decode('utf-8')
except KeyboardInterrupt:
pass

def authDevice(self) -> tuple[str, str]:
try:
res = _authDevice(self.account, self.authType, self.ctx, self.cookies)
if res.errStr.decode('utf-8') != '':
raise Exception(res.errStr.decode('utf-8'))
self.cookies = res.cookies
return res.cookies.decode('utf-8'), res.errStr.decode('utf-8')
except KeyboardInterrupt:
pass

def getCode(self) -> str:
return self.code

def getCookie(self) -> str:
return self.cookies

if __name__ == '__main__':

print('Test passwd')
auth = msAuth(account='[email protected]', authType='passwd', password='123456')
cookies, errStr = auth.auth()
print(cookies)

print('\nTest email')
auth = msAuth(account='[email protected]', authType='email')
auth.auth()
code = input('input code:')
cookies, errStr = auth.authEmail(code)
print(cookies)

print('\nTest device')
auth = msAuth(account='[email protected]', authType='device')
auth.auth()
print(auth.getCode())
cookies, errStr = auth.authDevice()
print(cookies)
87 changes: 87 additions & 0 deletions ms_auth/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package main

/*
struct Auth {
char* cookies;
char* ctx;
char* errStr;
};
*/
import "C"
import (
"encoding/json"
"os"
"os/signal"
"strings"
"syscall"

msauth "github.com/Harry-zklcdc/ms-auth"
)

func init() {
c := make(chan os.Signal, 2)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
<-c
os.Exit(1)
}()
}

func main() {}

//export auth
func auth(a, p, at *C.char) C.struct_Auth {
account := C.GoString(a)
passwd := C.GoString(p)
authType := C.GoString(at)
msau := msauth.NewAuth(account, passwd, authType)
cookiesRaw, err := msau.Auth()
if err != nil {
if !strings.HasPrefix(err.Error(), "device login need handler to continue") && err.Error() != "email login need code to continue" {
return C.struct_Auth{C.CString(""), C.CString(""), C.CString(err.Error())}
}
}
d, _ := json.Marshal(msau)
return C.struct_Auth{C.CString(cookiesRaw), C.CString(string(d)), C.CString(err.Error())}
}

//export authEmail
func authEmail(a, c, at, ctx, ck *C.char) C.struct_Auth {
account := C.GoString(a)
code := C.GoString(c)
authType := C.GoString(at)
context := C.GoString(ctx)
cookies := C.GoString(ck)
if authType != msauth.TYPE_EMAIL {
return C.struct_Auth{C.CString(""), C.CString(""), C.CString("auth type must be email")}
}
msau := msauth.NewAuth(account, "", authType)
msau.SetContext([]byte(context))
msau.SetCookie(cookies)
cookiesRaw, err := msau.AuthEmail(code)
if err != nil {
return C.struct_Auth{C.CString(""), C.CString(""), C.CString(err.Error())}
}
d, _ := json.Marshal(msau)
return C.struct_Auth{C.CString(cookiesRaw), C.CString(string(d)), C.CString("")}
}

//export authDevice
func authDevice(a, at, ctx, cookie *C.char) C.struct_Auth {
account := C.GoString(a)
authType := C.GoString(at)
context := C.GoString(ctx)
cookies := C.GoString(cookie)
if authType != msauth.TYPE_DEVICE {
return C.struct_Auth{C.CString(""), C.CString(""), C.CString("auth type must be device")}
}
msau := msauth.NewAuth(account, "", authType)
msau.SetContext([]byte(context))
msau.SetCookie(cookies)
cookiesRaw, err := msau.AuthDevice()
if err != nil {
return C.struct_Auth{C.CString(""), C.CString(""), C.CString(err.Error())}
}
d, _ := json.Marshal(msau)
return C.struct_Auth{C.CString(cookiesRaw), C.CString(string(d)), C.CString("")}
}
17 changes: 17 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from setuptools import setup, find_packages

setup(
name='ms_auth',
version='1.0.0',
description='Microsoft Login Lib',
author='Harry-zklcdc',
author_email='[email protected]',
packages=find_packages(),
package_data={'ms_auth':['*.so','*.dll']},
platforms=['linux', 'windows', 'macos'],
classifiers=[
'Intended Audience :: Developers',
'License :: OSI Approved :: AGPL-3.0',
'Programming Language :: Python :: 3',
],
)

0 comments on commit 2af2d25

Please sign in to comment.