Repository navigation
Added feature for story cleaning #92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
thatgirlginger
wants to merge
4
commits into
otwcode:master
Choose a base branch
from
thatgirlginger:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+297
−3
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| class Keywords: | ||
| def __init__(self): | ||
| self.notes = [ | ||
| "note", | ||
| "a/n", | ||
| "disclaimer", | ||
| "tumblr", | ||
| "author" | ||
| ] | ||
| self.warnings = [ | ||
| "warning", | ||
| "cw", | ||
| "content warning", | ||
| "trigger warning", | ||
| "tw", | ||
| ] | ||
| self.summary = [ | ||
| "summary", | ||
| "summaries", | ||
| "prompt", | ||
| "synopsis" | ||
| ] | ||
| self.commercial = [ | ||
| "patreon", | ||
| "ko-fi", | ||
| "kofundme", | ||
| ] | ||
| # self.ratings | ||
| # self.wordcount | ||
| # self.pairings | ||
| # self.characters | ||
| # others defined | ||
|
|
||
| def detect(self, type, text): | ||
| match type: | ||
| case "notes": | ||
| keywords = self.notes | ||
| case "warnings": | ||
| keywords = self.warnings | ||
| case "summary": | ||
| keywords = self.summary | ||
| case "commercial": | ||
| keywords = self.commercial | ||
| case _: | ||
| raise NameError( | ||
| "unsupported type: must be 'notes', 'warnings', 'summary', or 'commercial'; check config file" | ||
| ) | ||
| for k in keywords: | ||
| # eventually, a regex would be more efficient here, but with the line-by-line parsing built in this works for now | ||
| if k in text.lower(): | ||
| return True | ||
| return False | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| from colorama import Fore, Style | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a new library to this repo, so it needs to be added to the requirements.txt. |
||
|
|
||
|
|
||
| class Messaging: | ||
| """ | ||
| class that handles interactivity, message colors, etc | ||
| """ | ||
|
|
||
| def __init__(self, text): | ||
| self.text = text | ||
| self.summary_color = Fore.BLUE | ||
| self.notes_color = Fore.MAGENTA | ||
| self.warning_color = Fore.LIGHTBLUE_EX | ||
| self.commercial_color = Fore.RED | ||
| self.additional_lines_color = Fore.LIGHTBLACK_EX | ||
| self.general = Fore.GREEN | ||
| self.reset = Style.RESET_ALL | ||
|
|
||
| def check_init_response(self, type): | ||
| match type: | ||
| case "summary": | ||
| print(self.summary_color + f"{type}:\n" + self.reset + self.text) | ||
| case "notes": | ||
| print(self.notes_color + f"{type}:\n" + self.reset + self.text) | ||
| case "warnings": | ||
| print(self.warning_color + f"{type}:\n" + self.reset + self.text) | ||
| case "commercial": | ||
| print(self.commercial_color + f"{type}:\n" + self.reset + self.text) | ||
| r = input( | ||
| self.general | ||
| + "Enter 'n' if this is not correct, otherwise press any key to continue: \n" | ||
| + self.reset | ||
| ) | ||
| if r.lower() == "n": | ||
| return False | ||
| return True | ||
|
|
||
| def check_additional_lines(self, preview): | ||
| print(f"{self.text}\n") | ||
| print(self.additional_lines_color + preview + self.reset) | ||
| r = input( | ||
| ( | ||
| self.general | ||
| + "Enter 'n' if you would like to add the next line to the string identified and removed, otherwise press any key to continue: \n" | ||
| + self.reset | ||
| ) | ||
| ) | ||
| if r == "n": | ||
| return True | ||
| return False | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| import csv | ||
| import os | ||
|
|
||
|
|
||
| class OutputCSV: | ||
| def __init__(self, filename: str, columns: list): | ||
| self.filename = filename | ||
| self.columns = columns + ["story_identifier"] | ||
|
|
||
| def init_csv(self): | ||
| with open(self.filename, "w", encoding="utf_8_sig", newline="") as fp: | ||
| csvf = csv.DictWriter(fp, fieldnames=self.columns) | ||
| csvf.writeheader() | ||
|
|
||
| def write_data(self, data: dict): | ||
| with open(self.filename, "a", encoding="utf_8_sig", newline="") as f: | ||
| csvf = csv.DictWriter(f, fieldnames=self.columns) | ||
| csvf.writerow(data) | ||
|
|
||
|
|
||
| class OutputStoryFiles: | ||
| def __init__(self, output_path): | ||
| self.output_path = output_path | ||
|
|
||
| def strip_and_rewrite(self, text, options: dict): | ||
| text = "".join(text) | ||
| for o in options.keys(): | ||
| hit_lines = options[o].split("\n") | ||
| for h in hit_lines: | ||
| text = text.replace(h, "") | ||
| return text | ||
|
|
||
| def out_to_file(self, filename, strippedtext): | ||
| with open(os.path.join(self.output_path, filename), "w") as f: | ||
| f.write(strippedtext) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| from .keywords import Keywords | ||
| from .messages import Messaging | ||
|
|
||
|
|
||
| class Parser: | ||
| def __init__(self, textlines: list, options: list): | ||
| self.textlines = textlines | ||
| self.max = len(self.textlines) | ||
| self.options_dict = {} | ||
| for opt in options: | ||
| self.options_dict.update({opt: ""}) | ||
| self.end_message = "***no more lines to preview, press enter to continue***" | ||
| self.kwords = Keywords() | ||
|
|
||
| def detection_loop(self, type: str, i: int): | ||
| m = Messaging(self.textlines[i]) | ||
| if m.check_init_response(type): | ||
| local_count = i + 1 | ||
| txt = self.textlines[i] | ||
| try: | ||
| a = m.check_additional_lines(self.textlines[local_count]) | ||
| except IndexError: | ||
| input(self.end_message) | ||
| return txt | ||
| while a and local_count < self.max: | ||
| preview = self.textlines[local_count + 1] | ||
| txt = txt + self.textlines[local_count] | ||
| a = m.check_additional_lines(preview) | ||
| local_count += 1 | ||
| return txt | ||
| return "" | ||
|
|
||
| def parse_lines(self): | ||
| # this is per story file | ||
| for i in range(0, int(self.max)): | ||
| for o in self.options_dict.keys(): | ||
| if self.kwords.detect(o, self.textlines[i]): | ||
| self.options_dict[o] = ( | ||
| self.options_dict[o] + "\n" + self.detection_loop(o, i) | ||
| ) | ||
| return self.options_dict |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| import os | ||
| import shutil | ||
|
|
||
| from shared_python.Args import Args | ||
| from shared_python.Common import recursive_story_listdir | ||
|
|
||
| from story_cleanup.outputs import OutputCSV, OutputStoryFiles | ||
| from story_cleanup.parsing import Parser | ||
|
|
||
|
|
||
| # TODO: improve logging | ||
| """ | ||
| For archives where authors' notes and summaries are in the main body of text, this script scans for and removes them | ||
| note that this does /not/ load fields into the database tables, only extracts them to a CSV (and deletes if necessary) | ||
| """ | ||
|
|
||
| if __name__ == "__main__": | ||
| args_obj = Args() | ||
| args = args_obj.args_for_sn_extraction() | ||
| stories = recursive_story_listdir(args.chapters_path) | ||
| log = args_obj.logger_with_filename() | ||
|
|
||
| options = args.scan_types | ||
| to_remove = args.remove_option | ||
|
|
||
| csv = OutputCSV(args.output_csv, options) | ||
| j = int( | ||
| input("the index you left off at, if you are starting from scratch enter 0\n") | ||
| ) | ||
|
|
||
| if to_remove is not None and j == 0: | ||
| shutil.copytree(args.chapters_path, args.chapters_backup_path) | ||
| rewrite = OutputStoryFiles(args.chapters_path) | ||
|
|
||
| try: | ||
| # TODO: function that queries db for chapter and filenames | ||
| if j == 0: | ||
| csv.init_csv() | ||
| for s in stories[j:]: | ||
| log.info(f"story: {s}") | ||
| fname = os.path.join(args.chapters_path, s) | ||
| with open(fname, "r") as f: | ||
| text = f.readlines() | ||
| parser = Parser(text, options) | ||
| hits = parser.parse_lines() | ||
|
|
||
| if to_remove is not None: | ||
| new_text = rewrite.strip_and_rewrite(text, hits) | ||
| rewrite.out_to_file(s, new_text) | ||
|
|
||
| hits.update({"story_identifier": s}) | ||
| csv.write_data(hits) | ||
| j += 1 | ||
|
|
||
| except KeyboardInterrupt: | ||
| print(f"progress at restart: {j}") | ||
| except Exception as e: | ||
| print(f"there's been an error: {e}\n") | ||
| print(f"progress at restart: {j}") |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than list all combinations of cases, we could do a case-insensitive match later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can definitely do that.
i was also thinking about adding another config argument with more specific keywords, since this is one of those things that can vary a lot between archives. (in my own branch the notes keyword list alone has doubled).
do you think adding additional optional info in the YAML for this case would be ideal? i don't want anything to get too confusing or too bulky, but i also don't want to make the configuration too confusing