feat: usos sign-in, private calendar feed and timetable archive

This commit is contained in:
hh committed 2026-10-11 00:47:38 +00:00
commit 7d4e21f977
33 files changed
+3270

No files matched your search

+92
View File
@@ -0,0 +1,92 @@
package usos
import (
"crypto/hmac"
"crypto/rand"
"crypto/sha1"
"encoding/base64"
"encoding/hex"
"net/url"
"sort"
"strconv"
"strings"
"time"
)
const unreserved = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"
func percentEncode(s string) string {
var b strings.Builder
for i := range len(s) {
c := s[i]
if strings.IndexByte(unreserved, c) >= 0 {
b.WriteByte(c)
continue
}
b.WriteByte('%')
b.WriteString(strings.ToUpper(hex.EncodeToString([]byte{c})))
}
return b.String()
}
func signature(method, endpoint string, params url.Values, consumerSecret, tokenSecret string) string {
pairs := make([]string, 0, len(params))
for key, values := range params {
for _, value := range values {
pairs = append(pairs, percentEncode(key)+"="+percentEncode(value))
}
}
sort.Strings(pairs)
base := method + "&" + percentEncode(endpoint) + "&" + percentEncode(strings.Join(pairs, "&"))
mac := hmac.New(sha1.New, []byte(percentEncode(consumerSecret)+"&"+percentEncode(tokenSecret)))
mac.Write([]byte(base))
return base64.StdEncoding.EncodeToString(mac.Sum(nil))
}
func nonce() string {
buf := make([]byte, 16)
if _, err := rand.Read(buf); err != nil {
panic(err)
}
return hex.EncodeToString(buf)
}
func (c *Client) authorization(endpoint string, token *Token, params url.Values) (header string, body url.Values) {
oauth := url.Values{
"oauth_consumer_key": {c.Key},
"oauth_nonce": {nonce()},
"oauth_signature_method": {"HMAC-SHA1"},
"oauth_timestamp": {strconv.FormatInt(time.Now().Unix(), 10)},
"oauth_version": {"1.0"},
}
tokenSecret := ""
if token != nil {
oauth.Set("oauth_token", token.Key)
tokenSecret = token.Secret
}
body = url.Values{}
all := url.Values{}
for key, values := range params {
if strings.HasPrefix(key, "oauth_") {
oauth[key] = values
} else {
body[key] = values
}
all[key] = values
}
for key, values := range oauth {
all[key] = values
}
oauth.Set("oauth_signature", signature("POST", endpoint, all, c.Secret, tokenSecret))
keys := make([]string, 0, len(oauth))
for key := range oauth {
keys = append(keys, key)
}
sort.Strings(keys)
parts := make([]string, 0, len(keys))
for _, key := range keys {
parts = append(parts, key+`="`+percentEncode(oauth.Get(key))+`"`)
}
return "OAuth " + strings.Join(parts, ", "), body
}