Compare commits

...

46 Commits

Author SHA1 Message Date
7d0af09f86 Make the home dir 2023-03-18 00:11:50 -04:00
9b034619a8 Nvm 2023-03-18 00:05:02 -04:00
6482d52f0b WD Defaults to Home 2023-03-18 00:02:00 -04:00
cc252a367f Set Group 2023-03-18 00:00:29 -04:00
186d69cb53 Add handy group 2023-03-17 23:57:52 -04:00
fa6b0bad92 Run Service as Handy User 2023-03-17 23:56:14 -04:00
14c7249083 Test Write PDF Text 2023-03-17 23:51:49 -04:00
c5ce1629ef Basic OpenAI Summarize Function 2023-03-17 23:42:38 -04:00
06e2b7c641 Edit message properly 2023-03-17 23:28:11 -04:00
04005ea47d Simple Fix 2023-03-17 23:25:36 -04:00
1d4b5941e4 Truncate PDF URL 2023-03-17 23:23:36 -04:00
20b13af982 Print tostderr 2023-03-17 23:19:19 -04:00
a024de9165 Debug URL Print Statement 2023-03-17 23:16:56 -04:00
3034cf8aab BuffIO to read PDF COntent 2023-03-17 23:12:57 -04:00
3dc9bc1faa I promise I can type 2023-03-17 23:08:21 -04:00
b09fc1fa19 Add PDF Protocl 2023-03-17 23:06:56 -04:00
fa4a3bcf88 await getPDF 2023-03-17 23:04:31 -04:00
41b0a3e93b Whoops """ 2023-03-17 23:01:27 -04:00
f9ee755a29 Test getPDF Text 2023-03-17 22:59:18 -04:00
ca7a0c026a "find" title 2023-03-17 22:30:01 -04:00
7f50b237ae Debug Print 2023-03-17 22:23:40 -04:00
4837c0e628 div -> embed 2023-03-17 22:22:27 -04:00
389c91609a html_parser -> html.parser 2023-03-17 22:20:19 -04:00
b4253d58f1 Get PDF 2023-03-17 22:19:04 -04:00
ea21f8bb69 Soup! 2023-03-17 22:16:34 -04:00
4acdca9c43 Use SciHub Directly 2023-03-17 22:03:15 -04:00
596c257b77 Real Format String 2023-03-17 21:36:46 -04:00
5ba89a4019 Forgot some awaits 2023-03-17 21:35:54 -04:00
9238babde7 Test Search Func 2023-03-17 21:31:40 -04:00
81bd2e43ed They aren't Positional 2023-03-15 23:48:10 -04:00
60174e78b8 Basic Interaction Test 2023-03-15 23:45:03 -04:00
cc18438573 Add PR TODO 2023-03-15 23:35:20 -04:00
3ab7595d2c Whoops 2023-03-15 23:34:07 -04:00
71f114a59e Nextcord Forgets to State setuptools as dep 2023-03-15 23:32:13 -04:00
510759a005 Cleanup module 2023-03-15 23:14:57 -04:00
ca09506e7d Console Script Application 2023-03-15 23:04:46 -04:00
ee29c54eef Use Package not Application 2023-03-15 22:52:36 -04:00
7f860d0154 Don't use Default 2023-03-15 22:47:41 -04:00
c434a1d0c1 Remove vestigial path 2023-03-15 22:46:01 -04:00
efd334b04b Different ExecStart 2023-03-15 22:45:20 -04:00
a16b75b53a StartExec -> ExecStart 2023-03-15 22:37:52 -04:00
b35c267d2f Correct ServiceConfig? 2023-03-15 22:36:37 -04:00
321cb36793 Fix infinite recursion 2023-03-15 22:29:43 -04:00
b9a925af8e Modify service script 2023-03-15 22:28:56 -04:00
42560051d6 Correct Package Naming 2023-03-15 22:24:34 -04:00
b246a56510 Fix Secret Nix Config 2023-03-15 22:22:24 -04:00
7 changed files with 258 additions and 50 deletions

View File

@@ -3,30 +3,37 @@
inputs.handyhelper.url = "../";
outputs = { self, nixpkgs, handyhelper }: let
handy_overlay = (final: prev: {
handy_helper = handyhelper.packages."x86_64-linux".default;
});
system = "x86_64-linux";
handy_py = handyhelper.packages.${system}.handyhelper;
in {
nixosConfigurations."staging" = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
inherit system;
modules = [
../secrets/config.nix
({ config, pkgs, ... }: {
nixpkgs.overlays = [
handy_overlay
];
})
({lib, config, pkgs, ...}: {
../secrets/deploy.nix
({lib, config, pkgs, ...}: let
in {
systemd.services.handyhelper = {
wantedBy = ["networking-online.target"];
enable = true;
path = [
pkgs.handy_helper
];
script = ''
${pkgs.handy_helper}/bin/handyhelper.py
'';
serviceConfig = {
WorkingDirectory = config.users.users.handy.home;
ExecStart = ''
${handy_py}/bin/handyhelper
'';
User = "handy";
RuntimeDirectory = "handyhelper";
RuntimeDirectoryMode = "0755";
};
};
users.users = {
handy = {
home = "/var/lib/handyhelper";
useDefaultShell = true;
isSystemUser = true;
group = "handy";
};
};
users.groups.handy = {};
})
];
};

View File

@@ -11,9 +11,29 @@
outputs = { self, nixpkgs, flake-utils, poetry2nix }:
flake-utils.lib.eachDefaultSystem (system:
let
# see https://github.com/nix-community/poetry2nix/tree/master#api for more functions and examples.
inherit (poetry2nix.legacyPackages.${system}) mkPoetryApplication mkPoetryEnv;
inherit (poetry2nix.legacyPackages.${system}) mkPoetryApplication mkPoetryEnv mkPoetryPackages defaultPoetryOverrides;
pkgs = nixpkgs.legacyPackages.${system};
overrides = defaultPoetryOverrides.extend
(self: super: {
nextcord = super.nextcord.overridePythonAttrs
(
old: {
propagatedBuildInputs = (
old.propagatedBuildInputs or []
) ++ [super.setuptools];
}
);
pdftotext = super.pdftotext.overridePythonAttrs
(
old: {
buildInputs = (
old.buildInputs or []
) ++ (with pkgs; [
poppler
]);
}
);
});
in rec {
hydraJobs = pkgs.lib.optionalAttrs
@@ -44,18 +64,28 @@ DOC
'';
};
};
packages = {
handyhelper = mkPoetryApplication { projectDir = self; };
default = self.packages.${system}.myapp;
handyhelper = mkPoetryApplication {
projectDir = self;
# TODO: Upload to poetry2nix
# https://github.com/nix-community/poetry2nix/blob/master/docs/edgecases.md
inherit overrides;
};
default = self.packages.${system}.handyhelper;
};
devShells.default = pkgs.mkShell {
PYPROJECT_FILE = ./pyproject.toml;
packages = with pkgs; [
poetry2nix.packages.${system}.poetry
(mkPoetryEnv {
projectDir = self;
inherit overrides;
})
sops
# For pdftotext
poppler
];
};
}

View File

@@ -1 +1,103 @@
# Handle major modules of package
import nextcord as nc
from nextcord.ext import commands
from typing import Optional
import asyncio
import io
import os
import requests as req
from bs4 import BeautifulSoup as soup
import pdftotext
import sys
import openai
openai.api_key = os.getenv("OPENAI_KEY")
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
bot = commands.Bot()
async def search(txt):
url = "https://www.sci-hub.st/"
resp = req.post(url, data={
'request':txt
})
doc = soup(resp.text, 'html.parser')
if 'not found' in doc.find('title').get_text():
return None
ref = doc.find('div', {'id': 'citation'}).get_text()
pdf = doc.find('embed', {'id': 'pdf'})['src']
pdf = pdf[:(pdf.find(".pdf")+4)]
return {
'ref': ref,
'pdf': f"https:{pdf}"
}
async def getPDF(url):
eprint(f"Fetching PDF: {url}")
resp = req.get(url, stream=True)
pdf = io.BytesIO(resp.content)
pages = pdftotext.PDF(pdf)
with open("./test.txt","w") as f:
f.write("\n\n".join(pages))
return "\n\n".join(pages)
async def summarize(pdf):
completion = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "user", "content": f"""Please summarize the following research paper:
---
{pdf}
"""}
],
user="HandyHelper"
)
eprint(completion.usage)
return completion.choices[0].message
@bot.event
async def on_ready():
print(f'We have logged in as {bot.user}')
@bot.slash_command(name="summarize", description="Summarize all or part of an article", dm_permission=True)
async def summarize(
interaction: nc.Interaction,
article: str,
part: Optional[str] = nc.SlashOption(required=False)
):
await interaction.response.defer(ephemeral=False, with_message=True)
resp = await search(article)
if resp is None:
await interaction.followup.send(f"Unable to find article: {article}")
return
msg = await interaction.followup.send(f"""Article Found: {resp['ref']}
Processing PDF...""")
pdf = await getPDF(resp['pdf'])
await msg.edit(f"""Article Found: {resp['ref']}
```
{pdf[:1000]}
```""")
def main():
# TODO: Import bot token from env
bot.run(os.environ["DISCORD_TOKEN"])
if __name__ == "__main__":
print("Handy Helper has Begun!")
main()

View File

@@ -1,23 +0,0 @@
import nextcord
from nextcord.ext import commands
import os
bot = commands.Bot()
@bot.event
async def on_ready():
print(f'We have logged in as {bot.user}')
@bot.slash_command(name="summarize", description="Summarize all or part of an article", dm_permission=True)
async def summarize(
interaction: nextcord.Interaction,
article: str,
part: Optional[str] = SlashOption(required=False)
):
print("Will summarize article.")
# TODO: Import bot token from env
bot.run(os.environ["DISCORD_TOKEN"],)
if __name__ == "__main__":
print("Handy Helper has Begun!")

90
poetry.lock generated
View File

@@ -197,6 +197,25 @@ files = [
{file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"},
]
[[package]]
name = "beautifulsoup4"
version = "4.11.2"
description = "Screen-scraping library"
category = "main"
optional = false
python-versions = ">=3.6.0"
files = [
{file = "beautifulsoup4-4.11.2-py3-none-any.whl", hash = "sha256:0e79446b10b3ecb499c1556f7e228a53e64a2bfcebd455f370d8927cb5b59e39"},
{file = "beautifulsoup4-4.11.2.tar.gz", hash = "sha256:bc4bdda6717de5a2987436fb8d72f45dc90dd856bdfd512a1314ce90349a0106"},
]
[package.dependencies]
soupsieve = ">1.2"
[package.extras]
html5lib = ["html5lib"]
lxml = ["lxml"]
[[package]]
name = "certifi"
version = "2022.12.7"
@@ -298,7 +317,7 @@ files = [
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
category = "dev"
category = "main"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
files = [
@@ -619,6 +638,29 @@ docs = ["sphinx (==5.2.3)", "sphinxcontrib-websupport", "sphinxcontrib_trio (==1
speed = ["aiohttp[speedups]", "orjson (>=3.5.4)"]
voice = ["PyNaCl (>=1.3.0,<1.5)"]
[[package]]
name = "openai"
version = "0.27.2"
description = "Python client library for the OpenAI API"
category = "main"
optional = false
python-versions = ">=3.7.1"
files = [
{file = "openai-0.27.2-py3-none-any.whl", hash = "sha256:6df674cf257e9e0504f1fd191c333d3f6a2442b13218d0eccf06230eb24d320e"},
{file = "openai-0.27.2.tar.gz", hash = "sha256:5869fdfa34b0ec66c39afa22f4a0fb83a135dff81f6505f52834c6ab3113f762"},
]
[package.dependencies]
aiohttp = "*"
requests = ">=2.20"
tqdm = "*"
[package.extras]
datalib = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"]
dev = ["black (>=21.6b0,<22.0)", "pytest (>=6.0.0,<7.0.0)", "pytest-asyncio", "pytest-mock"]
embeddings = ["matplotlib", "numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "plotly", "scikit-learn (>=1.0.2)", "scipy", "tenacity (>=8.0.1)"]
wandb = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "wandb"]
[[package]]
name = "parso"
version = "0.8.3"
@@ -635,6 +677,17 @@ files = [
qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
testing = ["docopt", "pytest (<6.0.0)"]
[[package]]
name = "pdftotext"
version = "2.2.2"
description = "Simple PDF text extraction"
category = "main"
optional = false
python-versions = "*"
files = [
{file = "pdftotext-2.2.2.tar.gz", hash = "sha256:2a9aa89bc62022408781b39d188fabf5a3ad1103b6630f32c4e27e395f7966ee"},
]
[[package]]
name = "pexpect"
version = "4.8.0"
@@ -838,6 +891,18 @@ files = [
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
]
[[package]]
name = "soupsieve"
version = "2.4"
description = "A modern CSS selector implementation for Beautiful Soup."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "soupsieve-2.4-py3-none-any.whl", hash = "sha256:49e5368c2cda80ee7e84da9dbe3e110b70a4575f196efb74e51b94549d921955"},
{file = "soupsieve-2.4.tar.gz", hash = "sha256:e28dba9ca6c7c00173e34e4ba57448f0688bb681b7c5e8bf4971daafc093d69a"},
]
[[package]]
name = "stack-data"
version = "0.6.2"
@@ -858,6 +923,27 @@ pure-eval = "*"
[package.extras]
tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"]
[[package]]
name = "tqdm"
version = "4.65.0"
description = "Fast, Extensible Progress Meter"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "tqdm-4.65.0-py3-none-any.whl", hash = "sha256:c4f53a17fe37e132815abceec022631be8ffe1b9381c2e6e30aa70edc99e9671"},
{file = "tqdm-4.65.0.tar.gz", hash = "sha256:1871fb68a86b8fb3b59ca4cdd3dcccbc7e6d613eeed31f4c332531977b89beb5"},
]
[package.dependencies]
colorama = {version = "*", markers = "platform_system == \"Windows\""}
[package.extras]
dev = ["py-make (>=0.1.0)", "twine", "wheel"]
notebook = ["ipywidgets (>=6)"]
slack = ["slack-sdk"]
telegram = ["requests"]
[[package]]
name = "traitlets"
version = "5.9.0"
@@ -1081,4 +1167,4 @@ multidict = ">=4.0"
[metadata]
lock-version = "2.0"
python-versions = "^3.10"
content-hash = "92d541073d72547903239effa9d265802ef82c24f4207c0af3202e27d37954f6"
content-hash = "37cd0a0c44f8d8dc60f31db3cd1c01303d4ca07f85282c6a1823ed8135714313"

View File

@@ -6,10 +6,16 @@ authors = ["David Crompton"]
license = "MIT"
readme = "README.md"
[tool.poetry.scripts]
handyhelper = "handyhelper:main"
[tool.poetry.dependencies]
python = "^3.10"
requests = "^2.28.2"
nextcord = "^2.4.1"
openai = "^0.27.2"
beautifulsoup4 = "^4.11.2"
pdftotext = "^2.2.2"
[tool.poetry.group.dev.dependencies]
ipython = "^8.11.0"

View File

@@ -1,5 +1,5 @@
{
"data": "ENC[AES256_GCM,data:8YOc0g12Wq25MvgPN0jAvGQObdmmPs9ipchVjChr0DfnD724mpuMgiaLEiQti4RFLHDM7rg0jNJq8zileFxSTdC8MND0i0tEMM81oIV6p+L+5yf6vQqQ/aDTFRs0NdbPLMYjd5meVzUy6x5PhbBznJfdf7ZOxpri0s6PKtdCNV88Soxukwzp8Mf4MPUFtvYrvqjq+GrM7aVJU/nj9ZUzlmHsz32gpLhoO9AYXSJ2W3Se9zuP+S3QDS5RtRLTCLgzXF7n9KidGRRZrpI+lNA9J9Di80DDJ9Nd+AGO7/8W8UZYlQMVkKRXtNt+AWtXalzKaHl8ftIEfsgWe3Z6VtboaxJZ5EFweSxgjXjLdLtDUA9wnhHN7nAFaCBdE/91o/zhKjtzAisXBvf7kMStWkyxsBmEqjnNelDVLtqKAkOBNcq8cRr8YOF3Vyt1vBAXPz32h3mXTQXO8UNzE/pyl7Anny/eHXWT2tZXxxA=,iv:c3fb4wkWkqCfFthX+tYuWhVjSvIve3A5/5p1znI1164=,tag:pXtwwJnr9hvXOIwB9Wt99w==,type:str]",
"data": "ENC[AES256_GCM,data:wepRFTHhHt4vBz1ZTNUB0m4ECBvHEf7U7sCBNptuxzMX3xpk2Hrk9Cde4OT02UdNnaTSz0h4OANNh/2945CbRl87sFhR2/DY+P21LD240lhbWCgrbSUKgHjI0d+PyC0npOCv2+2cglJn+OsgYe4rrZlA8g6AbRejTJjnc5+jIDkj9VMX2TZCATuIRg2+8aHYr4tNq5Mfd4Y0OnF+VmQH/SDeap1YeUhh1l/6UEiuUrB4RvH+oNtZaDdDLI4Cg6sKXAeFcx8jejtYu59NDv4TiFi6EDZ4/WflWCvTuUqmG7qv8aBcKCK2tIfLPM6POD614I76v/suelZ+pSP0ij4UfC374tIB3CcO3v6MJpj3gwHz9+fomuYq4TC1g5moaVO2OU7oGfEIo5kKCeJpQX8o+qUjwZzpvP0y906Ow7tpBKZr2Se/w1k+IL0ZfzEtRhqN84M/U17pk+Yo0X5DzwLvPRc8rrUMmUNAUqv7W4cN13zakXaWhBBSkVwRnW2raJnW+u5Gd9l4UYz0QY1SpItC49Rm5zOsFWwt92BjV+LLT8pIiRsdDkevTuGuHVAyK3PAixNMPqMJ,iv:5gCuJnHiRVqb8wLgTgY74DbH6CYpmcXIlYBvne7sYF0=,tag:7eVarvHuNk3y3zHc8sDjTQ==,type:str]",
"sops": {
"kms": null,
"gcp_kms": null,
@@ -15,8 +15,8 @@
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtVWpxVTB3N2xpcXpDWlhI\naHM1TW9LL1FnT2lkRGF2bFM5VEVkNzRCV1djCkFqcmRLeWhYRkE0NzkvU00xcGdG\nYlpFOTlzWm9GS1BERi93QkxzOTJVN0EKLS0tIHpOYnlqMW9zaFpWaTJza2EzV1Jx\nOE1CUENlZlVKbGt6dUJUdUJuL1JmclkKFXf8F6bNDNDRpo+0X2MJKxAFls1vp/tr\n09dMExuNCHwJayKXlIL5+3OMDFTrjz49gZFQpWaOgQUbCVpI2Tff/A==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2023-03-15T23:27:35Z",
"mac": "ENC[AES256_GCM,data:kIWZqNDaAp0jxyFpVUzncM7AAm3u05V+FZrinZ95ftjV3ja9aLp8Ha1BVjg4csI8Yqk8Uc6IFXv9pnm6CnD2nWwPe2+W28hnIwP4B8SkiAoXj9dOT8gw5S+Vw0w8NoLFEGZ90xaiDdG5kfQCep9g4zWbqBHg397h1fxrTGJw5B8=,iv:An/IWRopuQ1RRSMgeXJcJuoL81SUtI8IsvY8asR984k=,tag:pLqRzKMv2VGWNCR8iOeskQ==,type:str]",
"lastmodified": "2023-03-18T03:32:23Z",
"mac": "ENC[AES256_GCM,data:cajh/+/3udzyWXaUMgcshsfsZ9WnLOCuFu3g/Dbu3riEARGuDf7vWEOFnjJbOvBwyXJ3Vcq7KaoB9x7vKC7vnNs982ffuvhxZTHyNEOs21UZB5IGszj0UCuXnHQJ+qMXVGYbFRU00KXh8e3bMwEe71fPq1iLLLFx82dllNl4Lng=,iv:oAvZNEYWASq+2v0O6ZP56EVI9YrjTeaDhUpcWEGiCE8=,tag:+E0fz422Axr996NBzcm4tg==,type:str]",
"pgp": null,
"unencrypted_suffix": "_unencrypted",
"version": "3.7.3"