diff --git a/README.md b/README.md
index eb76945..431d8fb 100644
--- a/README.md
+++ b/README.md
@@ -10,33 +10,33 @@ HuggingChat Python API
Leave a star :)
-> When you use this project, it means that you have agreed to the following two requirements of the HuggingChat:
+> When you use this project, it means that you have agreed to the following two requirements of the HuggingChat:
>
-> 1. AI is an area of active research with known problems such as biased generation and misinformation. Do not use this application for high-stakes decisions or advice.
+> 1. AI is an area of active research with known problems such as biased generation and misinformation. Do not use this application for high-stakes decisions or advice.
> 2. Your conversations will be shared with model authors.
-**Server resources are precious, it is not recommended to request this API in a high frequency.**
+**Server resources are precious, it is not recommended to request this API in a high frequency.**
(`Hugging Face's CTO🤗` just liked the suggestion)

-
-
## Authentication (Required Now)
-### Cookies
+### Get Cookies
-
-How to Get Cookies ?
+```python
+from hugchat.login import Login
-- Install the `Cookie-Editor` extension for [Chrome](https://chrome.google.com/webstore/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm) or [Firefox](https://addons.mozilla.org/en-US/firefox/addon/cookie-editor/)
-- Go to [HuggingChat](https://huggingface.co/chat) and **login**
-- Open the extension
-- Click `Export` on the bottom right, then `Export as JSON`(This saves your cookies to the clipboard)
-- Paste your cookies into a file `cookies.json`
+# login
+sign = Login(email, passwd)
+cookies = sign.login()
+sign.saveCookies()
-
+# load cookies from usercookies/.json
+sign = login(email, None)
+cookies = sign.loadCookies() # This will detect if the JSON file exists, return cookies if it does and raise an Exception if it's not.
+```
## Usage
@@ -48,7 +48,17 @@ pip install hugchat
```py
from hugchat import hugchat
-chatbot = hugchat.ChatBot(cookie_path="cookies.json") # or cookies=[...]
+from hugchat.login import Login
+
+# Log in to huggingface and grant authorization to huggingchat
+sign = Login(email, passwd)
+cookies = sign.login()
+
+# Save cookies to usercookies/.json
+sign.saveCookies()
+
+# Create a ChatBot
+chatbot = hugchat.ChatBot(cookies=cookies.get_dict()) # or cookie_path="usercookies/.json"
print(chatbot.chat("HI"))
# Create a new conversation
@@ -69,7 +79,7 @@ The `chat()` function receives these parameters:
- `truncate`: Optional[int]. Default is 1024
- `watermark`: Optional[bool]. Default is False
- `max_new_tokens`: Optional[int]. Default is 1024
-- `stop`: Optional[list]. Default is [""]
+- `stop`: Optional[list]. Default is ["``"]
- `return_full_text`: Optional[bool]. Default is False
- `stream`: Optional[bool]. Default is True
- `use_cache`: Optional[bool]. Default is False
@@ -96,4 +106,3 @@ Commands in cli mode:
## Disclaimers
This is not an official [Hugging Face](https://huggingface.co/) product. This is a **personal project** and is not affiliated with [Hugging Face](https://huggingface.co/) in any way. Don't sue us.
-
diff --git a/README_cn.md b/README_cn.md
index a1eb2ef..76e02c2 100644
--- a/README_cn.md
+++ b/README_cn.md
@@ -12,18 +12,21 @@ HuggingChat Python API
## 鉴权 (必需)
-### Cookies
+### 获取Cookies
-
-如何提取Cookies
+```python
+from hugchat.login import Login
-- 安装 [Chrome](https://chrome.google.com/webstore/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm) 或 [Firefox](https://addons.mozilla.org/en-US/firefox/addon/cookie-editor/) 的 cookie editor 扩展
-- 访问 [HuggingChat](https://huggingface.co/chat) 并 **登录**
-- 打开扩展程序
-- 点击右下角的"导出" (将会把内容保存到你的剪贴板上)
-- 把你剪贴板上的内容粘贴到 `cookies.json` 文件中
+# 登录
+sign = Login(email, passwd)
+cookies = sign.login()
+sign.saveCookies()
-
+# 从 usercookies/.json 中加载已保存的cookies
+sign = login(email, None)
+cookies = sign.loadCookies() # 这个方法会查询保存cookies的文件是否存在,存在就返回cookies,不存在就报错
+
+```
## 使用方式
@@ -35,14 +38,24 @@ pip install hugchat
```py
from hugchat import hugchat
-chatbot = hugchat.ChatBot(cookie_path="cookies.json") # 或者 cookies=[...]
-print(chatbot.chat("Hello!"))
+from hugchat.login import Login
+
+# 登入huggingface授权huggingchat
+sign = Login(email, passwd)
+cookies = sign.login()
+
+# 保存cookies至 usercookies/.json
+sign.saveCookies()
+
+# 创建一个 ChatBot
+chatbot = hugchat.ChatBot(cookies=cookies.get_dict()) # or cookie_path="usercookies/.json"
+print(chatbot.chat("HI"))
-# 创建一个新的会话
+# 创建一个新会话
id = chatbot.new_conversation()
chatbot.change_conversation(id)
-# 获取会话列表
+# 获取对话列表
conversation_list = chatbot.get_conversation_list()
```
@@ -56,7 +69,7 @@ conversation_list = chatbot.get_conversation_list()
- `truncate`: Optional[int]. Default is 1024
- `watermark`: Optional[bool]. Default is False
- `max_new_tokens`: Optional[int]. Default is 1024
-- `stop`: Optional[list]. Default is [""]
+- `stop`: Optional[list]. Default is ["``"]
- `return_full_text`: Optional[bool]. Default is False
- `stream`: Optional[bool]. Default is True
- `use_cache`: Optional[bool]. Default is False
diff --git a/src/hugchat/cli.py b/src/hugchat/cli.py
index 17c26b6..16faf09 100644
--- a/src/hugchat/cli.py
+++ b/src/hugchat/cli.py
@@ -7,7 +7,112 @@
to start cli.
"""
-from .hugchat import cli
+from .hugchat import ChatBot
+from .login import Login
+import getpass
+import argparse
+
+EMAIL = ""
+PASSWD = ""
+CHECK_BEFORE_PASSWORD = True
+
+def cli():
+ global EMAIL
+ global PASSWD
+ global CHECK_BEFORE_PASSWORD
+ print("-------HuggingChat-------")
+ print("Official Site: https://huggingface.co/chat")
+ print("1. AI is an area of active research with known problems such as biased generation and misinformation. Do not use this application for high-stakes decisions or advice.\n2. Your conversations will be shared with model authors.\nContinuing to use means that you accept the above points")
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ "-u",
+ type=str,
+ help="Your huggingface account's email"
+ )
+ parser.add_argument(
+ "-p",
+ action="store_true",
+ help="Require Password to login"
+ )
+ args = parser.parse_args()
+ email = args.u
+ inputpass = args.p
+ cookies = None
+ if CHECK_BEFORE_PASSWORD:
+ if not email:
+ email = EMAIL
+ try:
+ cookies = Login(email, None).loadCookies()
+ except Exception as e:
+ pass
+ if not cookies or inputpass:
+ if not email:
+ if EMAIL:
+ if not PASSWD or inputpass:
+ PASSWD = getpass.getpass("Password: ")
+ email = EMAIL
+ passwd = PASSWD
+ else:
+ raise Exception("No email specified. Please use '-u' or set it in cli.py")
+ else:
+ if inputpass or not PASSWD:
+ passwd = getpass.getpass("Password: ")
+ else:
+ passwd = PASSWD
+
+ print(f"Sign in as :{email}")
+ sign = Login(email, passwd)
+ try:
+ cookies = sign.loadCookies()
+ except Exception as e:
+ print(e)
+ print("Logging in...")
+ cookies = sign.login()
+ sign.saveCookies()
+
+ chatbot = ChatBot(cookies=cookies)
+ running = True
+ while running:
+ question = input("> ")
+ if question == "/new":
+ cid = chatbot.new_conversation()
+ print("The new conversation ID is: " + cid)
+ chatbot.change_conversation(cid)
+ print("Conversation changed successfully.")
+ continue
+
+ elif question.startswith("/switch"):
+ try:
+ conversations = chatbot.get_conversation_list()
+ conversation_id = str(question.split(" ")[1] if len(question.split(" ")) > 1 else "")
+ if conversation_id not in conversations:
+ print("# Please enter a valid ID number.")
+ print(f"# Sessions include: {conversations}")
+ else:
+ chatbot.change_conversation(conversation_id)
+ print(f"# Conversation switched successfully to {conversation_id}")
+ except ValueError:
+ print("# Please enter a valid ID number\n")
+
+
+
+ elif question == "/ids":
+ id_list = list(chatbot.get_conversation_list())
+ [print(f"{id_list.index(i)+1} : {i}{' ' if chatbot.current_conversation == i else ''}") for i in id_list]
+
+ elif question in ["/exit", "/quit","/close"]:
+ running = False
+
+ elif question.startswith("/"):
+ print("# Invalid command")
+
+ elif question == "":
+ pass
+
+ else:
+ res = chatbot.chat(question)
+ print("< " + res)
+
if __name__ == '__main__':
cli()
diff --git a/src/hugchat/hugchat.py b/src/hugchat/hugchat.py
index 7fe7f9a..fb7494d 100644
--- a/src/hugchat/hugchat.py
+++ b/src/hugchat/hugchat.py
@@ -1,9 +1,11 @@
from requests import Session
+import requests
import json
import os
import uuid
import logging
-
+import re
+import getpass
class ChatBot:
@@ -44,6 +46,7 @@ def __init__(
self.accepted_welcome_modal = False # Only when accepted, it can create a new conversation.
self.current_conversation = self.new_conversation()
+
def get_hc_session(self) -> Session:
session = Session()
# set cookies
@@ -261,52 +264,6 @@ def chat(
raise Exception(obj["error"])
return res_text
-def cli():
- print("-------HuggingChat-------")
- print("Official Site: https://huggingface.co/chat")
- print("1. AI is an area of active research with known problems such as biased generation and misinformation. Do not use this application for high-stakes decisions or advice.\n2. Your conversations will be shared with model authors.\nContinuing to use means that you accept the above points")
- chatbot = ChatBot(cookie_path="cookies.json")
- running = True
- while running:
- question = input("> ")
- if question == "/new":
- cid = chatbot.new_conversation()
- print("The new conversation ID is: " + cid)
- chatbot.change_conversation(cid)
- print("Conversation changed successfully.")
- continue
-
- elif question.startswith("/switch"):
- try:
- conversations = chatbot.get_conversation_list()
- conversation_id = str(question.split(" ")[1] if len(question.split(" ")) > 1 else "")
- if conversation_id not in conversations:
- print("# Please enter a valid ID number.")
- print(f"# Sessions include: {conversations}")
- else:
- chatbot.change_conversation(conversation_id)
- print(f"# Conversation switched successfully to {conversation_id}")
- except ValueError:
- print("# Please enter a valid ID number\n")
-
-
-
- elif question == "/ids":
- id_list = list(chatbot.get_conversation_list())
- [print(f"{id_list.index(i)+1} : {i}{' ' if chatbot.current_conversation == i else ''}") for i in id_list]
-
- elif question in ["/exit", "/quit","/close"]:
- running = False
-
- elif question.startswith("/"):
- print("# Invalid command")
-
- elif question == "":
- pass
-
- else:
- res = chatbot.chat(question)
- print("< " + res)
if __name__ == "__main__":
@@ -318,4 +275,3 @@ def cli():
sharelink = bot.share_conversation()
print(sharelink)
- cli()
\ No newline at end of file
diff --git a/src/hugchat/login.py b/src/hugchat/login.py
new file mode 100644
index 0000000..00bb881
--- /dev/null
+++ b/src/hugchat/login.py
@@ -0,0 +1,143 @@
+import requests
+import os
+import json
+import logging
+import re
+
+
+class Login:
+ def __init__(self, email: str, passwd: str) -> None:
+ self.COOKIE_DIR = os.path.dirname(os.path.abspath(__file__)) + "/usercookies"
+ self.COOKIE_PATH = self.COOKIE_DIR + f"/{email}.json"
+ if not os.path.exists(self.COOKIE_DIR):
+ logging.debug("Cookie directory not found, creating...")
+ os.makedirs(self.COOKIE_DIR)
+ logging.debug(f"Cookie store path: {self.COOKIE_DIR}")
+
+ self.email: str = email
+ self.passwd: str = passwd
+ self.headers = {
+ "Referer": "https://huggingface.co/",
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36 Edg/112.0.1722.64",
+ }
+ self.cookies = requests.sessions.RequestsCookieJar()
+
+ def requestsGet(self, url:str, params=None, allow_redirects=True) -> requests.Response:
+ res = requests.get(
+ url,
+ params=params,
+ headers=self.headers,
+ cookies=self.cookies,
+ allow_redirects=allow_redirects,
+ )
+ self.refreshCookies(res.cookies)
+ return res
+
+ def requestsPost(self, url:str, headers=None, params=None, data=None, stream=False, allow_redirects=True) -> requests.Response:
+ res = requests.post(
+ url,
+ stream=stream,
+ params=params,
+ data=data,
+ headers=self.headers if headers == None else headers,
+ cookies=self.cookies,
+ allow_redirects=allow_redirects
+ )
+ self.refreshCookies(res.cookies)
+ return res
+
+ def refreshCookies(self, cookies:requests.sessions.RequestsCookieJar):
+ dic = cookies.get_dict()
+ for i in dic:
+ self.cookies.set(i, dic[i])
+
+ def SigninWithEmail(self):
+ """
+ Login through your email and password.
+ PS: I found that it doesn't have any type of encrytion till now,
+ which could expose your password to the internet.
+ """
+ url = "https://huggingface.co/login"
+ data = {
+ "username": self.email,
+ "password": self.passwd,
+ }
+ res = self.requestsPost(url=url, data=data, allow_redirects=False)
+ if res.status_code == 400:
+ raise Exception("wrong username or password")
+
+ def getAuthURL(self):
+ url = "https://huggingface.co/chat/login"
+ headers = {
+ "Referer": "https://huggingface.co/chat/login",
+ "User-Agent": self.headers["User-Agent"],
+ "Content-Type": "application/x-www-form-urlencoded"
+ }
+ res = self.requestsPost(url, headers=headers, allow_redirects=False)
+ if res.status_code == 200:
+ # location = res.headers.get("Location", None)
+ location = res.json()["location"]
+ if location:
+ return location
+ else:
+ raise Exception("No authorize url found, please check your email or password.")
+ elif res.status_code == 303:
+ location = res.headers.get("Location")
+ if location:
+ return location
+ else:
+ raise Exception("No authorize url found, please check your email or password.")
+ else:
+ raise Exception("Something went wrong!")
+
+ def grantAuth(self, url: str) -> int:
+ """
+ Grant auth to huggingchat after login process is done.
+ """
+ res = self.requestsGet(url)
+ if res.status_code != 200:
+ raise Exception("Grant auth fatal!")
+ csrf = re.findall('/oauth/authorize.*?name="csrf" value="(.*?)"', res.text)
+ if len(csrf) == 0:
+ raise Exception("No csrf found!")
+ data = {
+ "csrf":csrf[0]
+ }
+
+ res = self.requestsPost(url, data=data, allow_redirects=False)
+ if res.status_code != 303:
+ raise Exception(f"get hf-chat cookies fatal! - {res.status_code}")
+ else:
+ location = res.headers.get("Location")
+ res = self.requestsGet(location, allow_redirects=False)
+ if res.status_code != 302:
+ raise Exception(f"get hf-chat cookie fatal! - {res.status_code}")
+ else:
+ return 1
+
+ def login(self) -> requests.sessions.RequestsCookieJar:
+ self.SigninWithEmail()
+ location = self.getAuthURL()
+ if self.grantAuth(location):
+ return self.cookies
+ else:
+ raise Exception(f"Grant auth fatal, please check your email or password\ncookies gained: \n{self.cookies}")
+
+ def saveCookies(self) -> str:
+ with open(self.COOKIE_PATH, "w", encoding="utf-8") as f:
+ f.write(json.dumps(self.cookies.get_dict(), ensure_ascii=False))
+ return self.COOKIE_PATH
+
+ def loadCookies(self) -> requests.sessions.RequestsCookieJar:
+ if os.path.exists(self.COOKIE_PATH):
+ with open(self.COOKIE_PATH, "r", encoding="utf-8") as f:
+ try:
+ js:dict = json.loads(f.read())
+ for i in js.keys():
+ self.cookies.set(i, js[i])
+ logging.debug(f"{i} loaded")
+ return self.cookies
+ except:
+ raise Exception("Load cookies from json file fatal. Error while parsing json file")
+ else:
+ raise Exception(f"{self.COOKIE_PATH} doesn't seem to exist")