Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5468d93976 | ||
|
|
d186f6f7da | ||
|
|
b5d52e4bb5 | ||
|
|
a2bdc66a03 | ||
|
|
bb72360699 | ||
|
|
adc15555e3 | ||
|
|
07ad626dd2 | ||
|
|
2729c984bc | ||
|
|
f3445b8e06 | ||
|
|
358f264bdd | ||
|
|
e3dda99233 | ||
|
|
7198e0be90 | ||
|
|
f9f0ed5085 | ||
|
|
b0c53a1511 | ||
|
|
54b9abc4b6 | ||
|
|
4ae14ff02e | ||
|
|
376eeab243 | ||
|
|
6d427849d5 | ||
|
|
ad8cb63541 | ||
|
|
57f8c24cee |
50
README.md
@@ -4,41 +4,39 @@ Given a subreddit name and a keyword, RPST will return all posts from a specifie
|
|||||||
[](https://github.com/rly0nheart/reddit-post-scraping-tool/actions/workflows/python-publish.yml) [](https://github.com/rly0nheart/reddit-post-scraping-tool/actions/workflows/codeql.yml)  
|
[](https://github.com/rly0nheart/reddit-post-scraping-tool/actions/workflows/python-publish.yml) [](https://github.com/rly0nheart/reddit-post-scraping-tool/actions/workflows/codeql.yml)  
|
||||||
|
|
||||||
# ✅ Features
|
# ✅ Features
|
||||||
## GUI
|
## *GUI*
|
||||||
- [x] Dark mode (*Right-click*)
|
- [x] Dark mode (*Right-click*).
|
||||||
- [x] Saves results to a JSON file (*Right-click*)
|
- [x] Saves results to a JSON file (*Right-click*).
|
||||||
- [x] Logs errors to a file
|
- [x] Logs errors to a file.
|
||||||
|
- [x] In-App feature to check for Updates.
|
||||||
|
|
||||||
## CLI
|
## *CLI*
|
||||||
- [x] Saves results to JSON (*specifiy* `--json`)
|
- [x] Saves results to JSON (*specifiy* `--json`).
|
||||||
- [x] Saves results to CSV (*specify* `--csv`)
|
- [x] Saves results to CSV (*specify* `--csv`).
|
||||||
- [x] Automatically checks for new updates, and notifies user if updates were found.
|
- [x] Automatically checks for new updates, and notifies user if updates were found.
|
||||||
|
|
||||||
# 📃 TODO
|
# 📃 TODO
|
||||||
## GUI
|
## *GUI*
|
||||||
- [ ] Make it installable with a setup.exe/setup.msi file.
|
- [ ] Make it installable with a setup.exe/setup.msi file.
|
||||||
- [x] Add manual dark mode option, that will be persistent in all sessions
|
- [x] Add manual dark mode option, that will be persistent in all sessions.
|
||||||
- [ ] Make it save results to a CSV file
|
- [x] Make settings persistent in all sessions.
|
||||||
|
- [x] Make it save results to a CSV file.
|
||||||
# Images & Screenshots
|
|
||||||
## GUI
|
|
||||||
* 
|
|
||||||
* 
|
|
||||||
|
|
||||||
## CLI
|
|
||||||
* 
|
|
||||||
* 
|
|
||||||
* 
|
|
||||||
|
|
||||||
|
|
||||||
|
# 🖥️ Tested environments
|
||||||
|
## *GUI*
|
||||||
|
- [x] Microsoft Windows 11
|
||||||
|
|
||||||
|
## *CLI*
|
||||||
|
- [x] Android Termux
|
||||||
|
- [x] Microsoft Windows 11
|
||||||
|
- [x] Ubuntu 22.04 - latest versions
|
||||||
|
|
||||||
# 📖 Wiki
|
# 📖 Wiki
|
||||||
[Refer to the Wiki](https://github.com/bellingcat/reddit-post-scraping-tool/wiki) for installation instructions, in addition to all other documentation.
|
[Refer to the Wiki](https://github.com/bellingcat/reddit-post-scraping-tool/wiki) for installation instructions, in addition to all other documentation.
|
||||||
|
|
||||||
# 😁 Donations
|
# 🖼️ Screenshots
|
||||||
If you like `RPST` and would like to show support, you can Buy A Coffee for the developer using the button below
|
You can view a collection of screenshots for both the *CLI* and *GUI* [here](https://github.com/bellingcat/reddit-post-scraping-tool/tree/master/images)
|
||||||
|
***
|
||||||
|
<a href="https://www.buymeacoffee.com/_rly0nheart"><img src="https://img.buymeacoffee.com/button-api/?text=Buy me a coffee&emoji=&slug=_rly0nheart&button_colour=40DCA5&font_colour=ffffff&font_family=Comic&outline_colour=000000&coffee_colour=FFDD00" /></a>
|
||||||
|
|
||||||
<a href="https://www.buymeacoffee.com/_rly0nheart" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Coffee" height="41" width="174"></a>
|

|
||||||
|
|
||||||
Your support will be much appreciated😊
|
|
||||||
|
|||||||
27
RPST GUI/RPST/AboutBox.Designer.vb
generated
@@ -26,9 +26,9 @@ Partial Class AboutBox
|
|||||||
PictureBoxLogo = New PictureBox()
|
PictureBoxLogo = New PictureBox()
|
||||||
LabelProgramName = New Label()
|
LabelProgramName = New Label()
|
||||||
LabelProgramDescription = New Label()
|
LabelProgramDescription = New Label()
|
||||||
LabelVersion = New Label()
|
|
||||||
LinkLabelReadtheWiki = New LinkLabel()
|
LinkLabelReadtheWiki = New LinkLabel()
|
||||||
Panel1 = New Panel()
|
Panel1 = New Panel()
|
||||||
|
LinkLabelVersion = New LinkLabel()
|
||||||
LicenseRichTextBox = New RichTextBox()
|
LicenseRichTextBox = New RichTextBox()
|
||||||
CType(PictureBoxLogo, ComponentModel.ISupportInitialize).BeginInit()
|
CType(PictureBoxLogo, ComponentModel.ISupportInitialize).BeginInit()
|
||||||
Panel1.SuspendLayout()
|
Panel1.SuspendLayout()
|
||||||
@@ -67,17 +67,6 @@ Partial Class AboutBox
|
|||||||
LabelProgramDescription.TabIndex = 4
|
LabelProgramDescription.TabIndex = 4
|
||||||
LabelProgramDescription.Text = "Description"
|
LabelProgramDescription.Text = "Description"
|
||||||
'
|
'
|
||||||
' LabelVersion
|
|
||||||
'
|
|
||||||
LabelVersion.AutoSize = True
|
|
||||||
LabelVersion.Font = New Font("Segoe UI", 9F, FontStyle.Underline, GraphicsUnit.Point)
|
|
||||||
LabelVersion.ForeColor = SystemColors.ControlText
|
|
||||||
LabelVersion.Location = New Point(347, 17)
|
|
||||||
LabelVersion.Name = "LabelVersion"
|
|
||||||
LabelVersion.Size = New Size(45, 15)
|
|
||||||
LabelVersion.TabIndex = 5
|
|
||||||
LabelVersion.Text = "Version"
|
|
||||||
'
|
|
||||||
' LinkLabelReadtheWiki
|
' LinkLabelReadtheWiki
|
||||||
'
|
'
|
||||||
LinkLabelReadtheWiki.AutoSize = True
|
LinkLabelReadtheWiki.AutoSize = True
|
||||||
@@ -92,15 +81,25 @@ Partial Class AboutBox
|
|||||||
' Panel1
|
' Panel1
|
||||||
'
|
'
|
||||||
Panel1.BackColor = SystemColors.Control
|
Panel1.BackColor = SystemColors.Control
|
||||||
|
Panel1.Controls.Add(LinkLabelVersion)
|
||||||
Panel1.Controls.Add(LabelProgramDescription)
|
Panel1.Controls.Add(LabelProgramDescription)
|
||||||
Panel1.Controls.Add(LabelProgramName)
|
Panel1.Controls.Add(LabelProgramName)
|
||||||
Panel1.Controls.Add(LinkLabelReadtheWiki)
|
Panel1.Controls.Add(LinkLabelReadtheWiki)
|
||||||
Panel1.Controls.Add(LabelVersion)
|
|
||||||
Panel1.Location = New Point(106, 12)
|
Panel1.Location = New Point(106, 12)
|
||||||
Panel1.Name = "Panel1"
|
Panel1.Name = "Panel1"
|
||||||
Panel1.Size = New Size(409, 93)
|
Panel1.Size = New Size(409, 93)
|
||||||
Panel1.TabIndex = 7
|
Panel1.TabIndex = 7
|
||||||
'
|
'
|
||||||
|
' LinkLabelVersion
|
||||||
|
'
|
||||||
|
LinkLabelVersion.AutoSize = True
|
||||||
|
LinkLabelVersion.Location = New Point(347, 17)
|
||||||
|
LinkLabelVersion.Name = "LinkLabelVersion"
|
||||||
|
LinkLabelVersion.Size = New Size(45, 15)
|
||||||
|
LinkLabelVersion.TabIndex = 7
|
||||||
|
LinkLabelVersion.TabStop = True
|
||||||
|
LinkLabelVersion.Text = "Version"
|
||||||
|
'
|
||||||
' LicenseRichTextBox
|
' LicenseRichTextBox
|
||||||
'
|
'
|
||||||
LicenseRichTextBox.Font = New Font("Cambria", 9.75F, FontStyle.Regular, GraphicsUnit.Point)
|
LicenseRichTextBox.Font = New Font("Cambria", 9.75F, FontStyle.Regular, GraphicsUnit.Point)
|
||||||
@@ -137,8 +136,8 @@ Partial Class AboutBox
|
|||||||
Friend WithEvents PictureBoxLogo As PictureBox
|
Friend WithEvents PictureBoxLogo As PictureBox
|
||||||
Friend WithEvents LabelProgramName As Label
|
Friend WithEvents LabelProgramName As Label
|
||||||
Friend WithEvents LabelProgramDescription As Label
|
Friend WithEvents LabelProgramDescription As Label
|
||||||
Friend WithEvents LabelVersion As Label
|
|
||||||
Friend WithEvents LinkLabelReadtheWiki As LinkLabel
|
Friend WithEvents LinkLabelReadtheWiki As LinkLabel
|
||||||
Friend WithEvents Panel1 As Panel
|
Friend WithEvents Panel1 As Panel
|
||||||
Friend WithEvents LicenseRichTextBox As RichTextBox
|
Friend WithEvents LicenseRichTextBox As RichTextBox
|
||||||
|
Friend WithEvents LinkLabelVersion As LinkLabel
|
||||||
End Class
|
End Class
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
<data name="Color1" type="System.Drawing.Color, System.Drawing"">Blue</data>
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -31,13 +31,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SO
|
|||||||
''' <param name="e">The event data.</param>
|
''' <param name="e">The event data.</param>
|
||||||
Private Sub AboutBox_Load(sender As Object, e As EventArgs) Handles MyBase.Load
|
Private Sub AboutBox_Load(sender As Object, e As EventArgs) Handles MyBase.Load
|
||||||
settings.LoadSettings()
|
settings.LoadSettings()
|
||||||
settings.ToggleDarkMode(settings.DarkMode)
|
settings.ToggleSettings(settings.DarkMode, "darkmode")
|
||||||
|
|
||||||
LabelProgramName.Text = My.Application.Info.ProductName
|
LabelProgramName.Text = My.Application.Info.ProductName
|
||||||
LabelProgramDescription.Text = "Given a subreddit name and a keyword,
|
LabelProgramDescription.Text = "Given a subreddit name and a keyword,
|
||||||
RPST returns all top posts (by default)
|
RPST returns all top posts (by default)
|
||||||
that contain the specified keyword."
|
that contain the specified keyword."
|
||||||
LabelVersion.Text = $"v{My.Application.Info.Version}"
|
LinkLabelVersion.Text = $"v{My.Application.Info.Version}"
|
||||||
LicenseRichTextBox.Text = LicenseText
|
LicenseRichTextBox.Text = LicenseText
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
@@ -50,4 +50,8 @@ that contain the specified keyword."
|
|||||||
Private Sub LinkLabelReadtheWiki_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) Handles LinkLabelReadtheWiki.LinkClicked
|
Private Sub LinkLabelReadtheWiki_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) Handles LinkLabelReadtheWiki.LinkClicked
|
||||||
Shell("cmd /c start https://github.com/bellingcat/reddit-post-scraping-tool/wiki")
|
Shell("cmd /c start https://github.com/bellingcat/reddit-post-scraping-tool/wiki")
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
|
Private Sub LinkLabelVersion_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) Handles LinkLabelVersion.LinkClicked
|
||||||
|
Shell($"cmd /c start https://github.com/bellingcat/reddit-post-scraping-tool/releases/tag/{My.Application.Info.Version}")
|
||||||
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
|
|||||||
@@ -6,32 +6,34 @@ Public Class DataGridViewHandler
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
''' <param name="dataGridView">The DataGridView to be initialized.</param>
|
''' <param name="dataGridView">The DataGridView to be initialized.</param>
|
||||||
Public Shared Sub AddColumn(dataGridView As DataGridView)
|
Public Shared Sub AddColumn(dataGridView As DataGridView)
|
||||||
' Clear the Columns and Rows before adding Items to them
|
''' <summary>
|
||||||
|
''' Clear the Columns and Rows before adding Items to them.
|
||||||
|
''' <summary>
|
||||||
dataGridView.Rows.Clear()
|
dataGridView.Rows.Clear()
|
||||||
dataGridView.Columns.Clear()
|
dataGridView.Columns.Clear()
|
||||||
|
|
||||||
dataGridView.Columns.Add("PostCount", "INDEX")
|
dataGridView.Columns.Add("PostCount", "🔢 Index")
|
||||||
dataGridView.Columns.Add("PostAuthor", "AUTHOR")
|
dataGridView.Columns.Add("PostAuthor", "👤 Author")
|
||||||
dataGridView.Columns.Add("PostID", "ID")
|
dataGridView.Columns.Add("PostID", "🆔 ID")
|
||||||
dataGridView.Columns.Add("PostText", "TEXT")
|
dataGridView.Columns.Add("PostText", "📝 Text")
|
||||||
dataGridView.Columns.Add("PostSubreddit", "SUBREDDIT")
|
dataGridView.Columns.Add("PostSubreddit", "🫂 Subreddit")
|
||||||
dataGridView.Columns.Add("SubredditVisibility", "VISIBILITY")
|
dataGridView.Columns.Add("SubredditVisibility", "🫣 Visibility")
|
||||||
dataGridView.Columns.Add("PostThumbnail", "THUMBNAIL")
|
dataGridView.Columns.Add("PostThumbnail", "🖼️ Thumbnail")
|
||||||
dataGridView.Columns.Add("PostIsNSFW", "NSFW")
|
dataGridView.Columns.Add("PostIsNSFW", "🔞 NSFW")
|
||||||
dataGridView.Columns.Add("PostIsGilded", "GILDED")
|
dataGridView.Columns.Add("PostIsGilded", "🥇 Gilded")
|
||||||
dataGridView.Columns.Add("PostUpvotes", "UPVOTES")
|
dataGridView.Columns.Add("PostUpvotes", "⬆️ Upvotes")
|
||||||
dataGridView.Columns.Add("PostUpvoteRatio", "UPVOTE RATIO")
|
dataGridView.Columns.Add("PostUpvoteRatio", "📊 Upvote Ratio")
|
||||||
dataGridView.Columns.Add("PostDownvotes", "DOWNVOTES")
|
dataGridView.Columns.Add("PostDownvotes", "⬇️ Downvotes")
|
||||||
dataGridView.Columns.Add("PostAwards", "AWARDS")
|
dataGridView.Columns.Add("PostAwards", "🏆 Awards")
|
||||||
dataGridView.Columns.Add("PostTopAward", "TOP AWARD")
|
dataGridView.Columns.Add("PostTopAward", "🏆 Top Award")
|
||||||
dataGridView.Columns.Add("PostIsCrosspostable", "IS CROSS-POSTABLE?")
|
dataGridView.Columns.Add("PostIsCrosspostable", "↪️ Is cross-postable?")
|
||||||
dataGridView.Columns.Add("PostScore", "SCORE")
|
dataGridView.Columns.Add("PostScore", "📈 Score")
|
||||||
dataGridView.Columns.Add("PostCategory", "CATEGORY")
|
dataGridView.Columns.Add("PostCategory", "🟢 Category")
|
||||||
dataGridView.Columns.Add("PostDomain", "DOMAIN")
|
dataGridView.Columns.Add("PostDomain", "🌐 Domain")
|
||||||
dataGridView.Columns.Add("PostPermalink", "PERMALINK")
|
dataGridView.Columns.Add("PostPermalink", "🔗 Permalink")
|
||||||
dataGridView.Columns.Add("PostCreatedAt", "CREATED AT")
|
dataGridView.Columns.Add("PostCreatedAt", "📅 Created At")
|
||||||
dataGridView.Columns.Add("PostApprovedAt", "APPROVED ATt")
|
dataGridView.Columns.Add("PostApprovedAt", "📅 Approved At")
|
||||||
dataGridView.Columns.Add("PostApprovedBy", "APPROVED BY")
|
dataGridView.Columns.Add("PostApprovedBy", "👤 Approved By")
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
Public Shared Sub AddRow(dataGridView As DataGridView, post As JObject, postNumber As Integer)
|
Public Shared Sub AddRow(dataGridView As DataGridView, post As JObject, postNumber As Integer)
|
||||||
|
|||||||
4
RPST GUI/RPST/DeveloperBox.Designer.vb
generated
@@ -61,7 +61,7 @@ Partial Class DeveloperBox
|
|||||||
GreetingLabel.TabIndex = 3
|
GreetingLabel.TabIndex = 3
|
||||||
GreetingLabel.Text = "👋🏾Hello, I'm Ritchie"
|
GreetingLabel.Text = "👋🏾Hello, I'm Ritchie"
|
||||||
'
|
'
|
||||||
' DeveloperForm
|
' DeveloperBox
|
||||||
'
|
'
|
||||||
AutoScaleDimensions = New SizeF(7F, 15F)
|
AutoScaleDimensions = New SizeF(7F, 15F)
|
||||||
AutoScaleMode = AutoScaleMode.Font
|
AutoScaleMode = AutoScaleMode.Font
|
||||||
@@ -73,7 +73,7 @@ Partial Class DeveloperBox
|
|||||||
FormBorderStyle = FormBorderStyle.FixedSingle
|
FormBorderStyle = FormBorderStyle.FixedSingle
|
||||||
MaximizeBox = False
|
MaximizeBox = False
|
||||||
MinimizeBox = False
|
MinimizeBox = False
|
||||||
Name = "DeveloperForm"
|
Name = "DeveloperBox"
|
||||||
ShowIcon = False
|
ShowIcon = False
|
||||||
ShowInTaskbar = False
|
ShowInTaskbar = False
|
||||||
StartPosition = FormStartPosition.CenterParent
|
StartPosition = FormStartPosition.CenterParent
|
||||||
|
|||||||
176
RPST GUI/RPST/FormMain.Designer.vb
generated
@@ -35,14 +35,15 @@ Partial Class FormMain
|
|||||||
LabelListing = New Label()
|
LabelListing = New Label()
|
||||||
LabelTimeframe = New Label()
|
LabelTimeframe = New Label()
|
||||||
ContextMenuStripRightClick = New ContextMenuStrip(components)
|
ContextMenuStripRightClick = New ContextMenuStrip(components)
|
||||||
ToolStripMenuItemDarkMode = New ToolStripMenuItem()
|
SettingsToolStripMenuItem = New ToolStripMenuItem()
|
||||||
ToolStripMenuItemSavePosts = New ToolStripMenuItem()
|
DarkModeToolStripMenuItem = New ToolStripMenuItem()
|
||||||
ToolStripMenuItemtoJSON = New ToolStripMenuItem()
|
SavePostsToolStripMenuItem = New ToolStripMenuItem()
|
||||||
ToolStripMenuItemtoCSV = New ToolStripMenuItem()
|
ToJSONToolStripMenuItem = New ToolStripMenuItem()
|
||||||
ToolStripMenuItemAbout = New ToolStripMenuItem()
|
ToCSVToolStripMenuItem = New ToolStripMenuItem()
|
||||||
ToolStripMenuItemDeveloper = New ToolStripMenuItem()
|
AboutToolStripMenuItem = New ToolStripMenuItem()
|
||||||
ToolStripMenuItemCheckUpdates = New ToolStripMenuItem()
|
DeveloperToolStripMenuItem = New ToolStripMenuItem()
|
||||||
ToolStripMenuItemQuit = New ToolStripMenuItem()
|
CheckForUpdatesToolStripMenuItem = New ToolStripMenuItem()
|
||||||
|
QuitToolStripMenuItem = New ToolStripMenuItem()
|
||||||
NumericUpDownLimit = New NumericUpDown()
|
NumericUpDownLimit = New NumericUpDown()
|
||||||
ToolTip = New ToolTip(components)
|
ToolTip = New ToolTip(components)
|
||||||
ContextMenuStripRightClick.SuspendLayout()
|
ContextMenuStripRightClick.SuspendLayout()
|
||||||
@@ -55,19 +56,19 @@ Partial Class FormMain
|
|||||||
TextBoxKeyword.ForeColor = SystemColors.WindowText
|
TextBoxKeyword.ForeColor = SystemColors.WindowText
|
||||||
TextBoxKeyword.Location = New Point(118, 20)
|
TextBoxKeyword.Location = New Point(118, 20)
|
||||||
TextBoxKeyword.Name = "TextBoxKeyword"
|
TextBoxKeyword.Name = "TextBoxKeyword"
|
||||||
TextBoxKeyword.PlaceholderText = "Keyword"
|
TextBoxKeyword.PlaceholderText = "*Keyword"
|
||||||
TextBoxKeyword.Size = New Size(100, 23)
|
TextBoxKeyword.Size = New Size(100, 23)
|
||||||
TextBoxKeyword.TabIndex = 0
|
TextBoxKeyword.TabIndex = 0
|
||||||
ToolTip.SetToolTip(TextBoxKeyword, "Enter the keyword you want to search for.")
|
ToolTip.SetToolTip(TextBoxKeyword, "[required] The keyword to search for.")
|
||||||
'
|
'
|
||||||
' TextBoxSubreddit
|
' TextBoxSubreddit
|
||||||
'
|
'
|
||||||
TextBoxSubreddit.Location = New Point(118, 49)
|
TextBoxSubreddit.Location = New Point(118, 49)
|
||||||
TextBoxSubreddit.Name = "TextBoxSubreddit"
|
TextBoxSubreddit.Name = "TextBoxSubreddit"
|
||||||
TextBoxSubreddit.PlaceholderText = "Subreddit"
|
TextBoxSubreddit.PlaceholderText = "*Subreddit"
|
||||||
TextBoxSubreddit.Size = New Size(100, 23)
|
TextBoxSubreddit.Size = New Size(100, 23)
|
||||||
TextBoxSubreddit.TabIndex = 4
|
TextBoxSubreddit.TabIndex = 4
|
||||||
ToolTip.SetToolTip(TextBoxSubreddit, "Provide the subreddit to search in.")
|
ToolTip.SetToolTip(TextBoxSubreddit, "[required] The subreddit to search in.")
|
||||||
'
|
'
|
||||||
' ButtonScrape
|
' ButtonScrape
|
||||||
'
|
'
|
||||||
@@ -76,7 +77,7 @@ Partial Class FormMain
|
|||||||
ButtonScrape.Size = New Size(51, 28)
|
ButtonScrape.Size = New Size(51, 28)
|
||||||
ButtonScrape.TabIndex = 6
|
ButtonScrape.TabIndex = 6
|
||||||
ButtonScrape.Text = "Scrape"
|
ButtonScrape.Text = "Scrape"
|
||||||
ToolTip.SetToolTip(ButtonScrape, "You can also just hit ENTER to start scraping.")
|
ToolTip.SetToolTip(ButtonScrape, "Hitting ENTER will also start the scraping process.")
|
||||||
ButtonScrape.UseVisualStyleBackColor = True
|
ButtonScrape.UseVisualStyleBackColor = True
|
||||||
'
|
'
|
||||||
' ComboBoxTimeframe
|
' ComboBoxTimeframe
|
||||||
@@ -91,7 +92,7 @@ Partial Class FormMain
|
|||||||
ComboBoxTimeframe.Size = New Size(100, 23)
|
ComboBoxTimeframe.Size = New Size(100, 23)
|
||||||
ComboBoxTimeframe.TabIndex = 8
|
ComboBoxTimeframe.TabIndex = 8
|
||||||
ComboBoxTimeframe.Text = "All"
|
ComboBoxTimeframe.Text = "All"
|
||||||
ToolTip.SetToolTip(ComboBoxTimeframe, "Select the time period for the posts. Default value is `All`.")
|
ToolTip.SetToolTip(ComboBoxTimeframe, "The time period for the posts. Default value is `All`.")
|
||||||
'
|
'
|
||||||
' ComboBoxListing
|
' ComboBoxListing
|
||||||
'
|
'
|
||||||
@@ -105,7 +106,7 @@ Partial Class FormMain
|
|||||||
ComboBoxListing.Size = New Size(100, 23)
|
ComboBoxListing.Size = New Size(100, 23)
|
||||||
ComboBoxListing.TabIndex = 9
|
ComboBoxListing.TabIndex = 9
|
||||||
ComboBoxListing.Text = "Top"
|
ComboBoxListing.Text = "Top"
|
||||||
ToolTip.SetToolTip(ComboBoxListing, "Choose the type of post listings. Default value is `Top`.")
|
ToolTip.SetToolTip(ComboBoxListing, "The type of post listings. Default value is `Top`.")
|
||||||
'
|
'
|
||||||
' LabelKeyword
|
' LabelKeyword
|
||||||
'
|
'
|
||||||
@@ -123,7 +124,7 @@ Partial Class FormMain
|
|||||||
LabelSubreddit.AutoEllipsis = True
|
LabelSubreddit.AutoEllipsis = True
|
||||||
LabelSubreddit.Font = New Font("Segoe UI Semibold", 9F, FontStyle.Bold Or FontStyle.Underline, GraphicsUnit.Point)
|
LabelSubreddit.Font = New Font("Segoe UI Semibold", 9F, FontStyle.Bold Or FontStyle.Underline, GraphicsUnit.Point)
|
||||||
LabelSubreddit.ForeColor = Color.Black
|
LabelSubreddit.ForeColor = Color.Black
|
||||||
LabelSubreddit.Location = New Point(19, 52)
|
LabelSubreddit.Location = New Point(19, 51)
|
||||||
LabelSubreddit.Name = "LabelSubreddit"
|
LabelSubreddit.Name = "LabelSubreddit"
|
||||||
LabelSubreddit.Size = New Size(71, 23)
|
LabelSubreddit.Size = New Size(71, 23)
|
||||||
LabelSubreddit.TabIndex = 11
|
LabelSubreddit.TabIndex = 11
|
||||||
@@ -134,7 +135,7 @@ Partial Class FormMain
|
|||||||
LabelLimit.AutoEllipsis = True
|
LabelLimit.AutoEllipsis = True
|
||||||
LabelLimit.Font = New Font("Segoe UI Semibold", 9F, FontStyle.Bold Or FontStyle.Underline, GraphicsUnit.Point)
|
LabelLimit.Font = New Font("Segoe UI Semibold", 9F, FontStyle.Bold Or FontStyle.Underline, GraphicsUnit.Point)
|
||||||
LabelLimit.ForeColor = Color.Black
|
LabelLimit.ForeColor = Color.Black
|
||||||
LabelLimit.Location = New Point(19, 75)
|
LabelLimit.Location = New Point(19, 80)
|
||||||
LabelLimit.Name = "LabelLimit"
|
LabelLimit.Name = "LabelLimit"
|
||||||
LabelLimit.Size = New Size(56, 23)
|
LabelLimit.Size = New Size(56, 23)
|
||||||
LabelLimit.TabIndex = 12
|
LabelLimit.TabIndex = 12
|
||||||
@@ -145,7 +146,7 @@ Partial Class FormMain
|
|||||||
LabelListing.AutoEllipsis = True
|
LabelListing.AutoEllipsis = True
|
||||||
LabelListing.Font = New Font("Segoe UI Semibold", 9F, FontStyle.Bold Or FontStyle.Underline, GraphicsUnit.Point)
|
LabelListing.Font = New Font("Segoe UI Semibold", 9F, FontStyle.Bold Or FontStyle.Underline, GraphicsUnit.Point)
|
||||||
LabelListing.ForeColor = Color.Black
|
LabelListing.ForeColor = Color.Black
|
||||||
LabelListing.Location = New Point(19, 107)
|
LabelListing.Location = New Point(19, 108)
|
||||||
LabelListing.Name = "LabelListing"
|
LabelListing.Name = "LabelListing"
|
||||||
LabelListing.Size = New Size(56, 23)
|
LabelListing.Size = New Size(56, 23)
|
||||||
LabelListing.TabIndex = 13
|
LabelListing.TabIndex = 13
|
||||||
@@ -156,7 +157,7 @@ Partial Class FormMain
|
|||||||
LabelTimeframe.AutoEllipsis = True
|
LabelTimeframe.AutoEllipsis = True
|
||||||
LabelTimeframe.Font = New Font("Segoe UI Semibold", 9F, FontStyle.Bold Or FontStyle.Underline, GraphicsUnit.Point)
|
LabelTimeframe.Font = New Font("Segoe UI Semibold", 9F, FontStyle.Bold Or FontStyle.Underline, GraphicsUnit.Point)
|
||||||
LabelTimeframe.ForeColor = Color.Black
|
LabelTimeframe.ForeColor = Color.Black
|
||||||
LabelTimeframe.Location = New Point(19, 136)
|
LabelTimeframe.Location = New Point(19, 137)
|
||||||
LabelTimeframe.Name = "LabelTimeframe"
|
LabelTimeframe.Name = "LabelTimeframe"
|
||||||
LabelTimeframe.Size = New Size(81, 23)
|
LabelTimeframe.Size = New Size(81, 23)
|
||||||
LabelTimeframe.TabIndex = 14
|
LabelTimeframe.TabIndex = 14
|
||||||
@@ -164,78 +165,85 @@ Partial Class FormMain
|
|||||||
'
|
'
|
||||||
' ContextMenuStripRightClick
|
' ContextMenuStripRightClick
|
||||||
'
|
'
|
||||||
ContextMenuStripRightClick.Items.AddRange(New ToolStripItem() {ToolStripMenuItemDarkMode, ToolStripMenuItemSavePosts, ToolStripMenuItemAbout, ToolStripMenuItemDeveloper, ToolStripMenuItemCheckUpdates, ToolStripMenuItemQuit})
|
ContextMenuStripRightClick.Items.AddRange(New ToolStripItem() {AboutToolStripMenuItem, DeveloperToolStripMenuItem, CheckForUpdatesToolStripMenuItem, SettingsToolStripMenuItem, QuitToolStripMenuItem})
|
||||||
ContextMenuStripRightClick.Name = "ContextMenuStrip1"
|
ContextMenuStripRightClick.Name = "ContextMenuStrip1"
|
||||||
ContextMenuStripRightClick.Size = New Size(154, 136)
|
ContextMenuStripRightClick.Size = New Size(172, 114)
|
||||||
'
|
'
|
||||||
' ToolStripMenuItemDarkMode
|
' SettingsToolStripMenuItem
|
||||||
'
|
'
|
||||||
ToolStripMenuItemDarkMode.AutoToolTip = True
|
SettingsToolStripMenuItem.DropDownItems.AddRange(New ToolStripItem() {DarkModeToolStripMenuItem, SavePostsToolStripMenuItem})
|
||||||
ToolStripMenuItemDarkMode.CheckOnClick = True
|
SettingsToolStripMenuItem.Image = CType(resources.GetObject("SettingsToolStripMenuItem.Image"), Image)
|
||||||
ToolStripMenuItemDarkMode.Image = CType(resources.GetObject("ToolStripMenuItemDarkMode.Image"), Image)
|
SettingsToolStripMenuItem.Name = "SettingsToolStripMenuItem"
|
||||||
ToolStripMenuItemDarkMode.Name = "ToolStripMenuItemDarkMode"
|
SettingsToolStripMenuItem.Size = New Size(171, 22)
|
||||||
ToolStripMenuItemDarkMode.Size = New Size(153, 22)
|
SettingsToolStripMenuItem.Text = "Settings"
|
||||||
ToolStripMenuItemDarkMode.Text = "Dark Mode"
|
|
||||||
'
|
'
|
||||||
' ToolStripMenuItemSavePosts
|
' DarkModeToolStripMenuItem
|
||||||
'
|
'
|
||||||
ToolStripMenuItemSavePosts.AutoToolTip = True
|
DarkModeToolStripMenuItem.CheckOnClick = True
|
||||||
ToolStripMenuItemSavePosts.DropDownItems.AddRange(New ToolStripItem() {ToolStripMenuItemtoJSON, ToolStripMenuItemtoCSV})
|
DarkModeToolStripMenuItem.Image = CType(resources.GetObject("DarkModeToolStripMenuItem.Image"), Image)
|
||||||
ToolStripMenuItemSavePosts.Image = CType(resources.GetObject("ToolStripMenuItemSavePosts.Image"), Image)
|
DarkModeToolStripMenuItem.Name = "DarkModeToolStripMenuItem"
|
||||||
ToolStripMenuItemSavePosts.Name = "ToolStripMenuItemSavePosts"
|
DarkModeToolStripMenuItem.Size = New Size(180, 22)
|
||||||
ToolStripMenuItemSavePosts.Size = New Size(153, 22)
|
DarkModeToolStripMenuItem.Text = "Dark Mode"
|
||||||
ToolStripMenuItemSavePosts.Text = "Save Posts"
|
|
||||||
ToolStripMenuItemSavePosts.ToolTipText = "Save found posts to..."
|
|
||||||
'
|
'
|
||||||
' ToolStripMenuItemtoJSON
|
' SavePostsToolStripMenuItem
|
||||||
'
|
'
|
||||||
ToolStripMenuItemtoJSON.AutoToolTip = True
|
SavePostsToolStripMenuItem.AutoToolTip = True
|
||||||
ToolStripMenuItemtoJSON.CheckOnClick = True
|
SavePostsToolStripMenuItem.DropDownItems.AddRange(New ToolStripItem() {ToJSONToolStripMenuItem, ToCSVToolStripMenuItem})
|
||||||
ToolStripMenuItemtoJSON.Image = CType(resources.GetObject("ToolStripMenuItemtoJSON.Image"), Image)
|
SavePostsToolStripMenuItem.Image = CType(resources.GetObject("SavePostsToolStripMenuItem.Image"), Image)
|
||||||
ToolStripMenuItemtoJSON.Name = "ToolStripMenuItemtoJSON"
|
SavePostsToolStripMenuItem.Name = "SavePostsToolStripMenuItem"
|
||||||
ToolStripMenuItemtoJSON.Size = New Size(116, 22)
|
SavePostsToolStripMenuItem.Size = New Size(180, 22)
|
||||||
ToolStripMenuItemtoJSON.Text = "to JSON"
|
SavePostsToolStripMenuItem.Text = "Save posts"
|
||||||
'
|
'
|
||||||
' ToolStripMenuItemtoCSV
|
' ToJSONToolStripMenuItem
|
||||||
'
|
'
|
||||||
ToolStripMenuItemtoCSV.AutoToolTip = True
|
ToJSONToolStripMenuItem.AutoToolTip = True
|
||||||
ToolStripMenuItemtoCSV.Enabled = False
|
ToJSONToolStripMenuItem.CheckOnClick = True
|
||||||
ToolStripMenuItemtoCSV.Image = CType(resources.GetObject("ToolStripMenuItemtoCSV.Image"), Image)
|
ToJSONToolStripMenuItem.Image = CType(resources.GetObject("ToJSONToolStripMenuItem.Image"), Image)
|
||||||
ToolStripMenuItemtoCSV.Name = "ToolStripMenuItemtoCSV"
|
ToJSONToolStripMenuItem.Name = "ToJSONToolStripMenuItem"
|
||||||
ToolStripMenuItemtoCSV.Size = New Size(116, 22)
|
ToJSONToolStripMenuItem.Size = New Size(180, 22)
|
||||||
ToolStripMenuItemtoCSV.Text = "to CSV"
|
ToJSONToolStripMenuItem.Text = "to JSON"
|
||||||
'
|
'
|
||||||
' ToolStripMenuItemAbout
|
' ToCSVToolStripMenuItem
|
||||||
'
|
'
|
||||||
ToolStripMenuItemAbout.AutoToolTip = True
|
ToCSVToolStripMenuItem.AutoToolTip = True
|
||||||
ToolStripMenuItemAbout.Image = CType(resources.GetObject("ToolStripMenuItemAbout.Image"), Image)
|
ToCSVToolStripMenuItem.CheckOnClick = True
|
||||||
ToolStripMenuItemAbout.Name = "ToolStripMenuItemAbout"
|
ToCSVToolStripMenuItem.Image = CType(resources.GetObject("ToCSVToolStripMenuItem.Image"), Image)
|
||||||
ToolStripMenuItemAbout.Size = New Size(153, 22)
|
ToCSVToolStripMenuItem.Name = "ToCSVToolStripMenuItem"
|
||||||
ToolStripMenuItemAbout.Text = "About"
|
ToCSVToolStripMenuItem.Size = New Size(180, 22)
|
||||||
|
ToCSVToolStripMenuItem.Text = "to CSV"
|
||||||
'
|
'
|
||||||
' ToolStripMenuItemDeveloper
|
' AboutToolStripMenuItem
|
||||||
'
|
'
|
||||||
ToolStripMenuItemDeveloper.AutoToolTip = True
|
AboutToolStripMenuItem.AutoToolTip = True
|
||||||
ToolStripMenuItemDeveloper.Image = CType(resources.GetObject("ToolStripMenuItemDeveloper.Image"), Image)
|
AboutToolStripMenuItem.Image = CType(resources.GetObject("AboutToolStripMenuItem.Image"), Image)
|
||||||
ToolStripMenuItemDeveloper.Name = "ToolStripMenuItemDeveloper"
|
AboutToolStripMenuItem.Name = "AboutToolStripMenuItem"
|
||||||
ToolStripMenuItemDeveloper.Size = New Size(153, 22)
|
AboutToolStripMenuItem.Size = New Size(171, 22)
|
||||||
ToolStripMenuItemDeveloper.Text = "Developer"
|
AboutToolStripMenuItem.Text = "About"
|
||||||
'
|
'
|
||||||
' ToolStripMenuItemCheckUpdates
|
' DeveloperToolStripMenuItem
|
||||||
'
|
'
|
||||||
ToolStripMenuItemCheckUpdates.AutoToolTip = True
|
DeveloperToolStripMenuItem.AutoToolTip = True
|
||||||
ToolStripMenuItemCheckUpdates.Image = CType(resources.GetObject("ToolStripMenuItemCheckUpdates.Image"), Image)
|
DeveloperToolStripMenuItem.Image = CType(resources.GetObject("DeveloperToolStripMenuItem.Image"), Image)
|
||||||
ToolStripMenuItemCheckUpdates.Name = "ToolStripMenuItemCheckUpdates"
|
DeveloperToolStripMenuItem.Name = "DeveloperToolStripMenuItem"
|
||||||
ToolStripMenuItemCheckUpdates.Size = New Size(153, 22)
|
DeveloperToolStripMenuItem.Size = New Size(171, 22)
|
||||||
ToolStripMenuItemCheckUpdates.Text = "Check Updates"
|
DeveloperToolStripMenuItem.Text = "Developer"
|
||||||
'
|
'
|
||||||
' ToolStripMenuItemQuit
|
' CheckForUpdatesToolStripMenuItem
|
||||||
'
|
'
|
||||||
ToolStripMenuItemQuit.AutoToolTip = True
|
CheckForUpdatesToolStripMenuItem.AutoToolTip = True
|
||||||
ToolStripMenuItemQuit.Image = CType(resources.GetObject("ToolStripMenuItemQuit.Image"), Image)
|
CheckForUpdatesToolStripMenuItem.Image = CType(resources.GetObject("CheckForUpdatesToolStripMenuItem.Image"), Image)
|
||||||
ToolStripMenuItemQuit.Name = "ToolStripMenuItemQuit"
|
CheckForUpdatesToolStripMenuItem.Name = "CheckForUpdatesToolStripMenuItem"
|
||||||
ToolStripMenuItemQuit.Size = New Size(153, 22)
|
CheckForUpdatesToolStripMenuItem.Size = New Size(171, 22)
|
||||||
ToolStripMenuItemQuit.Text = "Quit"
|
CheckForUpdatesToolStripMenuItem.Text = "Check for Updates"
|
||||||
|
'
|
||||||
|
' QuitToolStripMenuItem
|
||||||
|
'
|
||||||
|
QuitToolStripMenuItem.AutoToolTip = True
|
||||||
|
QuitToolStripMenuItem.Font = New Font("Segoe UI Semibold", 9F, FontStyle.Bold, GraphicsUnit.Point)
|
||||||
|
QuitToolStripMenuItem.Image = CType(resources.GetObject("QuitToolStripMenuItem.Image"), Image)
|
||||||
|
QuitToolStripMenuItem.Name = "QuitToolStripMenuItem"
|
||||||
|
QuitToolStripMenuItem.Size = New Size(171, 22)
|
||||||
|
QuitToolStripMenuItem.Text = "Quit"
|
||||||
'
|
'
|
||||||
' NumericUpDownLimit
|
' NumericUpDownLimit
|
||||||
'
|
'
|
||||||
@@ -245,7 +253,7 @@ Partial Class FormMain
|
|||||||
NumericUpDownLimit.ReadOnly = True
|
NumericUpDownLimit.ReadOnly = True
|
||||||
NumericUpDownLimit.Size = New Size(100, 23)
|
NumericUpDownLimit.Size = New Size(100, 23)
|
||||||
NumericUpDownLimit.TabIndex = 15
|
NumericUpDownLimit.TabIndex = 15
|
||||||
ToolTip.SetToolTip(NumericUpDownLimit, "Set how many posts you want to go through. Default value is `10`.")
|
ToolTip.SetToolTip(NumericUpDownLimit, "Number of posts to go through. Default value is `10`.")
|
||||||
NumericUpDownLimit.Value = New Decimal(New Integer() {10, 0, 0, 0})
|
NumericUpDownLimit.Value = New Decimal(New Integer() {10, 0, 0, 0})
|
||||||
'
|
'
|
||||||
' ToolTip
|
' ToolTip
|
||||||
@@ -298,14 +306,16 @@ Partial Class FormMain
|
|||||||
Friend WithEvents LabelListing As Label
|
Friend WithEvents LabelListing As Label
|
||||||
Friend WithEvents LabelTimeframe As Label
|
Friend WithEvents LabelTimeframe As Label
|
||||||
Friend WithEvents ContextMenuStripRightClick As ContextMenuStrip
|
Friend WithEvents ContextMenuStripRightClick As ContextMenuStrip
|
||||||
Friend WithEvents ToolStripMenuItemSavePosts As ToolStripMenuItem
|
Friend WithEvents SavePostsToolStripMenuItem As ToolStripMenuItem
|
||||||
Friend WithEvents ToolStripMenuItemtoJSON As ToolStripMenuItem
|
Friend WithEvents ToJSONToolStripMenuItem As ToolStripMenuItem
|
||||||
Friend WithEvents ToolStripMenuItemtoCSV As ToolStripMenuItem
|
Friend WithEvents ToCSVToolStripMenuItem As ToolStripMenuItem
|
||||||
Friend WithEvents NumericUpDownLimit As NumericUpDown
|
Friend WithEvents NumericUpDownLimit As NumericUpDown
|
||||||
Friend WithEvents ToolStripMenuItemDarkMode As ToolStripMenuItem
|
Friend WithEvents AboutToolStripMenuItem As ToolStripMenuItem
|
||||||
Friend WithEvents ToolStripMenuItemAbout As ToolStripMenuItem
|
Friend WithEvents DeveloperToolStripMenuItem As ToolStripMenuItem
|
||||||
Friend WithEvents ToolStripMenuItemDeveloper As ToolStripMenuItem
|
Friend WithEvents CheckForUpdatesToolStripMenuItem As ToolStripMenuItem
|
||||||
Friend WithEvents ToolStripMenuItemCheckUpdates As ToolStripMenuItem
|
Friend WithEvents QuitToolStripMenuItem As ToolStripMenuItem
|
||||||
Friend WithEvents ToolStripMenuItemQuit As ToolStripMenuItem
|
|
||||||
Friend WithEvents ToolTip As ToolTip
|
Friend WithEvents ToolTip As ToolTip
|
||||||
|
Friend WithEvents SettingsToolStripMenuItem As ToolStripMenuItem
|
||||||
|
Friend WithEvents DarkModeToolStripMenuItem As ToolStripMenuItem
|
||||||
|
Friend WithEvents SaveFoundPostsToolStripMenuItem As ToolStripMenuItem
|
||||||
End Class
|
End Class
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
Imports System.IO
|
Imports Newtonsoft.Json.Linq
|
||||||
Imports System.Windows.Forms.VisualStyles.VisualStyleElement
|
|
||||||
Imports Newtonsoft.Json
|
|
||||||
Imports Newtonsoft.Json.Linq
|
|
||||||
|
|
||||||
Public Class FormMain
|
Public Class FormMain
|
||||||
ReadOnly settings As New SettingsManager()
|
ReadOnly settings As New SettingsManager()
|
||||||
@@ -14,32 +11,25 @@ Public Class FormMain
|
|||||||
''' <param name="sender">The source of the event.</param>
|
''' <param name="sender">The source of the event.</param>
|
||||||
''' <param name="e">An EventArgs that contains the event data.</param>
|
''' <param name="e">An EventArgs that contains the event data.</param>
|
||||||
Private Sub FormMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
|
Private Sub FormMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
|
||||||
|
|
||||||
settings.LoadSettings()
|
settings.LoadSettings()
|
||||||
settings.ToggleDarkMode(settings.DarkMode)
|
settings.ToggleSettings(settings.DarkMode, "darkmode")
|
||||||
|
settings.ToggleSettings(settings.SaveToJson, "json")
|
||||||
|
settings.ToggleSettings(settings.SaveToCsv, "csv")
|
||||||
|
|
||||||
Utilities.PathFinder()
|
Utilities.PathFinder()
|
||||||
Utilities.LogFirstTimeLaunch()
|
Utilities.LogFirstTimeLaunch()
|
||||||
Me.Text = My.Application.Info.AssemblyName
|
Me.Text = My.Application.Info.AssemblyName
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
|
|
||||||
''' <summary>
|
|
||||||
''' Event handler for the 'Dark Mode' checkbox change event.
|
|
||||||
''' It toggles the dark mode of the application based on the checkbox status.
|
|
||||||
''' </summary>
|
|
||||||
''' <param name="sender">The source of the event.</param>
|
|
||||||
''' <param name="e">An EventArgs that contains the event data.</param>
|
|
||||||
Private Sub DarkModeToolStripMenuItem_CheckedChanged(sender As Object, e As EventArgs) Handles ToolStripMenuItemDarkMode.CheckedChanged
|
|
||||||
settings.ToggleDarkMode(ToolStripMenuItemDarkMode.Checked)
|
|
||||||
End Sub
|
|
||||||
|
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' Event handler for the 'About' menu item click.
|
''' Event handler for the 'About' menu item click.
|
||||||
''' It shows the 'About' box.
|
''' It shows the 'About' box.
|
||||||
''' </summary>
|
''' </summary>
|
||||||
''' <param name="sender">The source of the event.</param>
|
''' <param name="sender">The source of the event.</param>
|
||||||
''' <param name="e">An EventArgs that contains the event data.</param>
|
''' <param name="e">An EventArgs that contains the event data.</param>
|
||||||
Private Sub ToolStripMenuItemAbout_Click(sender As Object, e As EventArgs) Handles ToolStripMenuItemAbout.Click
|
Private Sub ToolStripMenuItemAbout_Click(sender As Object, e As EventArgs) Handles AboutToolStripMenuItem.Click
|
||||||
AboutBox.Show()
|
AboutBox.Show()
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
@@ -50,7 +40,7 @@ Public Class FormMain
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
''' <param name="sender">The source of the event.</param>
|
''' <param name="sender">The source of the event.</param>
|
||||||
''' <param name="e">An EventArgs that contains the event data.</param>
|
''' <param name="e">An EventArgs that contains the event data.</param>
|
||||||
Private Sub ToolStripMenuItemDeveloper_Click(sender As Object, e As EventArgs) Handles ToolStripMenuItemDeveloper.Click
|
Private Sub ToolStripMenuItemDeveloper_Click(sender As Object, e As EventArgs) Handles DeveloperToolStripMenuItem.Click
|
||||||
DeveloperBox.ShowDialog()
|
DeveloperBox.ShowDialog()
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
@@ -61,7 +51,7 @@ Public Class FormMain
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
''' <param name="sender">The source of the event.</param>
|
''' <param name="sender">The source of the event.</param>
|
||||||
''' <param name="e">An EventArgs that contains the event data.</param>
|
''' <param name="e">An EventArgs that contains the event data.</param>
|
||||||
Private Sub ToolStripMenuItemCheckUpdates_Click(sender As Object, e As EventArgs) Handles ToolStripMenuItemCheckUpdates.Click
|
Private Sub ToolStripMenuItemCheckUpdates_Click(sender As Object, e As EventArgs) Handles CheckForUpdatesToolStripMenuItem.Click
|
||||||
Dim data As JObject = ApiHandler.CheckUpdates()
|
Dim data As JObject = ApiHandler.CheckUpdates()
|
||||||
If data("tag_name").ToString = My.Application.Info.Version.ToString Then
|
If data("tag_name").ToString = My.Application.Info.Version.ToString Then
|
||||||
MessageBox.Show($"You're running the latest version v{My.Application.Info.Version} of {Me.Text}. Check again soon! :)", $"{Me.Text} v{My.Application.Info.Version}", MessageBoxButtons.OK, MessageBoxIcon.Information)
|
MessageBox.Show($"You're running the latest version v{My.Application.Info.Version} of {Me.Text}. Check again soon! :)", $"{Me.Text} v{My.Application.Info.Version}", MessageBoxButtons.OK, MessageBoxIcon.Information)
|
||||||
@@ -83,7 +73,7 @@ Public Class FormMain
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
''' <param name="sender">The source of the event.</param>
|
''' <param name="sender">The source of the event.</param>
|
||||||
''' <param name="e">An EventArgs that contains the event data.</param>
|
''' <param name="e">An EventArgs that contains the event data.</param>
|
||||||
Private Sub ToolStripMenuItemQuit_Click(sender As Object, e As EventArgs) Handles ToolStripMenuItemQuit.Click
|
Private Sub ToolStripMenuItemQuit_Click(sender As Object, e As EventArgs) Handles QuitToolStripMenuItem.Click
|
||||||
Dim result As DialogResult = MessageBox.Show("This will close the program, continue?", "Quit", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
|
Dim result As DialogResult = MessageBox.Show("This will close the program, continue?", "Quit", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
|
||||||
If result = DialogResult.Yes Then
|
If result = DialogResult.Yes Then
|
||||||
Me.Close()
|
Me.Close()
|
||||||
@@ -99,7 +89,8 @@ Public Class FormMain
|
|||||||
''' <param name="sender">The sender of the event.</param>
|
''' <param name="sender">The sender of the event.</param>
|
||||||
''' <param name="e">The EventArgs instance containing the event data.</param>
|
''' <param name="e">The EventArgs instance containing the event data.</param>
|
||||||
Private Sub ButtonScrape_Click(sender As Object, e As EventArgs) Handles ButtonScrape.Click
|
Private Sub ButtonScrape_Click(sender As Object, e As EventArgs) Handles ButtonScrape.Click
|
||||||
Utilities.ProcessRedditPosts(ToolStripMenuItemtoJSON)
|
settings.LoadSettings()
|
||||||
|
PostsProcessor.ProcessRedditPosts(settings:=settings)
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
|
|
||||||
@@ -110,11 +101,13 @@ Public Class FormMain
|
|||||||
''' <param name="sender">The source of the event.</param>
|
''' <param name="sender">The source of the event.</param>
|
||||||
''' <param name="e">The <see cref="KeyEventArgs"/> instance containing the event data.</param>
|
''' <param name="e">The <see cref="KeyEventArgs"/> instance containing the event data.</param>
|
||||||
Private Sub TextBoxKeyword_KeyDown(sender As Object, e As KeyEventArgs) Handles TextBoxKeyword.KeyDown
|
Private Sub TextBoxKeyword_KeyDown(sender As Object, e As KeyEventArgs) Handles TextBoxKeyword.KeyDown
|
||||||
|
settings.LoadSettings()
|
||||||
|
|
||||||
' Check if the Enter key is pressed
|
' Check if the Enter key is pressed
|
||||||
If e.KeyCode = Keys.Enter Then
|
If e.KeyCode = Keys.Enter Then
|
||||||
' Prevent the beep sound that usually comes with the Enter key in a single-line TextBox
|
' Prevent the beep sound that usually comes with the Enter key in a single-line TextBox
|
||||||
e.SuppressKeyPress = True
|
e.SuppressKeyPress = True
|
||||||
Utilities.ProcessRedditPosts(ToolStripMenuItemtoJSON)
|
PostsProcessor.ProcessRedditPosts(settings:=settings)
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
@@ -126,11 +119,13 @@ Public Class FormMain
|
|||||||
''' <param name="sender">The source of the event.</param>
|
''' <param name="sender">The source of the event.</param>
|
||||||
''' <param name="e">The <see cref="KeyEventArgs"/> instance containing the event data.</param>
|
''' <param name="e">The <see cref="KeyEventArgs"/> instance containing the event data.</param>
|
||||||
Private Sub TextBoxSubreddit_KeyDown(sender As Object, e As KeyEventArgs) Handles TextBoxSubreddit.KeyDown
|
Private Sub TextBoxSubreddit_KeyDown(sender As Object, e As KeyEventArgs) Handles TextBoxSubreddit.KeyDown
|
||||||
|
settings.LoadSettings()
|
||||||
|
|
||||||
' Check if the Enter key is pressed
|
' Check if the Enter key is pressed
|
||||||
If e.KeyCode = Keys.Enter Then
|
If e.KeyCode = Keys.Enter Then
|
||||||
' Prevent the beep sound that usually comes with the Enter key in a single-line TextBox
|
' Prevent the beep sound that usually comes with the Enter key in a single-line TextBox
|
||||||
e.SuppressKeyPress = True
|
e.SuppressKeyPress = True
|
||||||
Utilities.ProcessRedditPosts(ToolStripMenuItemtoJSON)
|
PostsProcessor.ProcessRedditPosts(settings:=settings)
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
@@ -142,11 +137,13 @@ Public Class FormMain
|
|||||||
''' <param name="sender">The source of the event.</param>
|
''' <param name="sender">The source of the event.</param>
|
||||||
''' <param name="e">The <see cref="KeyEventArgs"/> instance containing the event data.</param>
|
''' <param name="e">The <see cref="KeyEventArgs"/> instance containing the event data.</param>
|
||||||
Private Sub NumericUpDownLimit_KeyDown(sender As Object, e As KeyEventArgs) Handles NumericUpDownLimit.KeyDown
|
Private Sub NumericUpDownLimit_KeyDown(sender As Object, e As KeyEventArgs) Handles NumericUpDownLimit.KeyDown
|
||||||
|
settings.LoadSettings()
|
||||||
|
|
||||||
' Check if the Enter key is pressed
|
' Check if the Enter key is pressed
|
||||||
If e.KeyCode = Keys.Enter Then
|
If e.KeyCode = Keys.Enter Then
|
||||||
' Prevent the beep sound that usually comes with the Enter key in a single-line TextBox
|
' Prevent the beep sound that usually comes with the Enter key in a single-line TextBox
|
||||||
e.SuppressKeyPress = True
|
e.SuppressKeyPress = True
|
||||||
Utilities.ProcessRedditPosts(ToolStripMenuItemtoJSON)
|
PostsProcessor.ProcessRedditPosts(settings:=settings)
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
@@ -158,11 +155,13 @@ Public Class FormMain
|
|||||||
''' <param name="sender">The source of the event.</param>
|
''' <param name="sender">The source of the event.</param>
|
||||||
''' <param name="e">The <see cref="KeyEventArgs"/> instance containing the event data.</param>
|
''' <param name="e">The <see cref="KeyEventArgs"/> instance containing the event data.</param>
|
||||||
Private Sub ComboBoxListing_KeyDown(sender As Object, e As KeyEventArgs) Handles ComboBoxListing.KeyDown
|
Private Sub ComboBoxListing_KeyDown(sender As Object, e As KeyEventArgs) Handles ComboBoxListing.KeyDown
|
||||||
|
settings.LoadSettings()
|
||||||
|
|
||||||
' Check if the Enter key is pressed
|
' Check if the Enter key is pressed
|
||||||
If e.KeyCode = Keys.Enter Then
|
If e.KeyCode = Keys.Enter Then
|
||||||
' Prevent the beep sound that usually comes with the Enter key in a single-line TextBox
|
' Prevent the beep sound that usually comes with the Enter key in a single-line TextBox
|
||||||
e.SuppressKeyPress = True
|
e.SuppressKeyPress = True
|
||||||
Utilities.ProcessRedditPosts(ToolStripMenuItemtoJSON)
|
PostsProcessor.ProcessRedditPosts(settings:=settings)
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
@@ -174,11 +173,43 @@ Public Class FormMain
|
|||||||
''' <param name="sender">The source of the event.</param>
|
''' <param name="sender">The source of the event.</param>
|
||||||
''' <param name="e">The <see cref="KeyEventArgs"/> instance containing the event data.</param>
|
''' <param name="e">The <see cref="KeyEventArgs"/> instance containing the event data.</param>
|
||||||
Private Sub ComboBoxTimeframe_KeyDown(sender As Object, e As KeyEventArgs) Handles ComboBoxTimeframe.KeyDown
|
Private Sub ComboBoxTimeframe_KeyDown(sender As Object, e As KeyEventArgs) Handles ComboBoxTimeframe.KeyDown
|
||||||
|
settings.LoadSettings()
|
||||||
|
|
||||||
' Check if the Enter key is pressed
|
' Check if the Enter key is pressed
|
||||||
If e.KeyCode = Keys.Enter Then
|
If e.KeyCode = Keys.Enter Then
|
||||||
' Prevent the beep sound that usually comes with the Enter key in a single-line TextBox
|
' Prevent the beep sound that usually comes with the Enter key in a single-line TextBox
|
||||||
e.SuppressKeyPress = True
|
e.SuppressKeyPress = True
|
||||||
Utilities.ProcessRedditPosts(ToolStripMenuItemtoJSON)
|
PostsProcessor.ProcessRedditPosts(settings:=settings)
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
|
''' <summary>
|
||||||
|
''' Event handler for the 'Dark Mode' checkbox change event.
|
||||||
|
''' It toggles the dark mode of the application based on the checkbox status.
|
||||||
|
''' </summary>
|
||||||
|
''' <param name="sender">The source of the event.</param>
|
||||||
|
''' <param name="e">An EventArgs that contains the event data.</param>
|
||||||
|
Private Sub ToolStripMenuItemDarkMode_CheckedChanged(sender As Object, e As EventArgs) Handles DarkModeToolStripMenuItem.CheckedChanged
|
||||||
|
settings.ToggleSettings(DarkModeToolStripMenuItem.Checked, "darkmode")
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
''' <summary>
|
||||||
|
''' Event handler for the 'to CSV' checkbox change event.
|
||||||
|
''' It toggles the dark mode of the application based on the checkbox status.
|
||||||
|
''' </summary>
|
||||||
|
''' <param name="sender">The source of the event.</param>
|
||||||
|
''' <param name="e">An EventArgs that contains the event data.</param>
|
||||||
|
Private Sub ToCSVToolStripMenuItem_CheckedChanged(sender As Object, e As EventArgs) Handles ToCSVToolStripMenuItem.CheckedChanged
|
||||||
|
settings.ToggleSettings(ToCSVToolStripMenuItem.Checked, "csv")
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
''' <summary>
|
||||||
|
''' Event handler for the 'to JSON' checkbox change event.
|
||||||
|
''' It toggles the dark mode of the application based on the checkbox status.
|
||||||
|
''' </summary>
|
||||||
|
''' <param name="sender">The source of the event.</param>
|
||||||
|
''' <param name="e">An EventArgs that contains the event data.</param>
|
||||||
|
Private Sub ToJSONToolStripMenuItem_CheckedChanged(sender As Object, e As EventArgs) Handles ToJSONToolStripMenuItem.CheckedChanged
|
||||||
|
settings.ToggleSettings(ToJSONToolStripMenuItem.Checked, "json")
|
||||||
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
|
|||||||
@@ -26,4 +26,63 @@ Public Class PostsProcessor
|
|||||||
Return post("data")("selftext").ToString.ToLower(Globalization.CultureInfo.InvariantCulture).Contains(keyword.ToLower(System.Globalization.CultureInfo.InvariantCulture))
|
Return post("data")("selftext").ToString.ToLower(Globalization.CultureInfo.InvariantCulture).Contains(keyword.ToLower(System.Globalization.CultureInfo.InvariantCulture))
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
|
|
||||||
|
''' <summary>
|
||||||
|
''' Collects user inputs, fetches Reddit posts based on the inputs, checks if posts contain the keyword, and saves posts to a JSON file if necessary.
|
||||||
|
''' </summary>
|
||||||
|
''' <param name="JSONToolStripMenuItem">Indicates whether to save the posts to a JSON file.</param>
|
||||||
|
''' <remarks>
|
||||||
|
''' This function initializes the DataGridView, iterates over each post, adds the posts containing the keyword to the DataGridView and updates the UI.
|
||||||
|
''' It also shows a message if the keyword was not found in any of the posts or if the inputs are empty.
|
||||||
|
''' </remarks>
|
||||||
|
Public Shared Sub ProcessRedditPosts(settings)
|
||||||
|
' Collect inputs from the user.
|
||||||
|
Dim inputs = Utilities.CollectInputs()
|
||||||
|
|
||||||
|
If inputs.HasValue Then
|
||||||
|
' Initialize the DataGridView.
|
||||||
|
DataGridViewHandler.AddColumn(FormPosts.DataGridViewPosts)
|
||||||
|
|
||||||
|
' Fetch Reddit posts based on the inputs.
|
||||||
|
Dim processor As New PostsProcessor()
|
||||||
|
Dim posts As JObject = processor.FetchPosts(inputs.Value.Subreddit, inputs.Value.Listing, inputs.Value.Limit, inputs.Value.Timeframe)
|
||||||
|
Dim totalPosts As Integer = 0
|
||||||
|
Dim keywordFound As Boolean = False
|
||||||
|
Dim foundPosts As Integer = 0
|
||||||
|
Dim foundPostsList As New JArray
|
||||||
|
|
||||||
|
' Iterate over each post.
|
||||||
|
For Each post In posts("data")("children")
|
||||||
|
totalPosts += 1
|
||||||
|
' Check if the post contains the keyword
|
||||||
|
If PostsProcessor.PostContainsKeyword(post, inputs.Value.Keyword.ToLower(Globalization.CultureInfo.InvariantCulture)) Then
|
||||||
|
foundPosts += 1
|
||||||
|
foundPostsList.Add(post)
|
||||||
|
' Add the post to the DataGridView.
|
||||||
|
DataGridViewHandler.AddRow(FormPosts.DataGridViewPosts, post, totalPosts)
|
||||||
|
FormPosts.Show()
|
||||||
|
keywordFound = True
|
||||||
|
End If
|
||||||
|
Next
|
||||||
|
|
||||||
|
' Check if the keyword was found in any posts
|
||||||
|
If Not keywordFound Then
|
||||||
|
MessageBox.Show($"Keyword `{inputs.Value.Keyword}` was not found in any of the " + posts("data")("children").Count.ToString(Globalization.CultureInfo.InvariantCulture) _
|
||||||
|
+ $" {inputs.Value.Listing} posts from r/{inputs.Value.Subreddit}", "Not Found", MessageBoxButtons.OK, MessageBoxIcon.Warning)
|
||||||
|
End If
|
||||||
|
|
||||||
|
|
||||||
|
If settings.SaveToJson Then
|
||||||
|
' Save posts to a JSON file if SaveToJson is True.
|
||||||
|
Utilities.SavePostsToJson(foundPostsList)
|
||||||
|
End If
|
||||||
|
|
||||||
|
If settings.SaveToCsv Then
|
||||||
|
' Save posts to a CSV file if SaveToCsv is True.
|
||||||
|
Utilities.SavePostsToCSV(foundPostsList)
|
||||||
|
End If
|
||||||
|
Else
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
|
||||||
End Class
|
End Class
|
||||||
|
|||||||
@@ -4,41 +4,39 @@ Given a subreddit name and a keyword, RPST will return all posts from a specifie
|
|||||||
[](https://github.com/rly0nheart/reddit-post-scraping-tool/actions/workflows/python-publish.yml) [](https://github.com/rly0nheart/reddit-post-scraping-tool/actions/workflows/codeql.yml)  
|
[](https://github.com/rly0nheart/reddit-post-scraping-tool/actions/workflows/python-publish.yml) [](https://github.com/rly0nheart/reddit-post-scraping-tool/actions/workflows/codeql.yml)  
|
||||||
|
|
||||||
# ✅ Features
|
# ✅ Features
|
||||||
## GUI
|
## *GUI*
|
||||||
- [x] Dark mode (*Right-click*)
|
- [x] Dark mode (*Right-click*).
|
||||||
- [x] Saves results to a JSON file (*Right-click*)
|
- [x] Saves results to a JSON file (*Right-click*).
|
||||||
- [x] Logs errors to a file
|
- [x] Logs errors to a file.
|
||||||
|
- [x] In-App feature to check for Updates.
|
||||||
|
|
||||||
## CLI
|
## *CLI*
|
||||||
- [x] Saves results to JSON (*specifiy* `--json`)
|
- [x] Saves results to JSON (*specifiy* `--json`).
|
||||||
- [x] Saves results to CSV (*specify* `--csv`)
|
- [x] Saves results to CSV (*specify* `--csv`).
|
||||||
- [x] Automatically checks for new updates, and notifies user if updates were found.
|
- [x] Automatically checks for new updates, and notifies user if updates were found.
|
||||||
|
|
||||||
# 📃 TODO
|
# 📃 TODO
|
||||||
## GUI
|
## *GUI*
|
||||||
- [ ] Make it installable with a setup.exe/setup.msi file.
|
- [ ] Make it installable with a setup.exe/setup.msi file.
|
||||||
- [x] Add manual dark mode option, that will be persistent in all sessions
|
- [x] Add manual dark mode option, that will be persistent in all sessions.
|
||||||
- [ ] Make it save results to a CSV file
|
- [x] Make settings persistent in all sessions.
|
||||||
|
- [x] Make it save results to a CSV file.
|
||||||
# Images & Screenshots
|
|
||||||
## GUI
|
|
||||||
* 
|
|
||||||
* 
|
|
||||||
|
|
||||||
## CLI
|
|
||||||
* 
|
|
||||||
* 
|
|
||||||
* 
|
|
||||||
|
|
||||||
|
|
||||||
|
# 🖥️ Tested environments
|
||||||
|
## *GUI*
|
||||||
|
- [x] Microsoft Windows 11
|
||||||
|
|
||||||
|
## *CLI*
|
||||||
|
- [x] Android Termux
|
||||||
|
- [x] Microsoft Windows 11
|
||||||
|
- [x] Ubuntu 22.04 - latest versions
|
||||||
|
|
||||||
# 📖 Wiki
|
# 📖 Wiki
|
||||||
[Refer to the Wiki](https://github.com/bellingcat/reddit-post-scraping-tool/wiki) for installation instructions, in addition to all other documentation.
|
[Refer to the Wiki](https://github.com/bellingcat/reddit-post-scraping-tool/wiki) for installation instructions, in addition to all other documentation.
|
||||||
|
|
||||||
# 😁 Donations
|
# 🖼️ Screenshots
|
||||||
If you like `RPST` and would like to show support, you can Buy A Coffee for the developer using the button below
|
You can view a collection of screenshots for both the *CLI* and *GUI* [here](https://github.com/bellingcat/reddit-post-scraping-tool/tree/master/images)
|
||||||
|
***
|
||||||
|
<a href="https://www.buymeacoffee.com/_rly0nheart"><img src="https://img.buymeacoffee.com/button-api/?text=Buy me a coffee&emoji=&slug=_rly0nheart&button_colour=40DCA5&font_colour=ffffff&font_family=Comic&outline_colour=000000&coffee_colour=FFDD00" /></a>
|
||||||
|
|
||||||
<a href="https://www.buymeacoffee.com/_rly0nheart" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Coffee" height="41" width="174"></a>
|

|
||||||
|
|
||||||
Your support will be much appreciated😊
|
|
||||||
|
|||||||
@@ -13,11 +13,11 @@
|
|||||||
<PackageProjectUrl>https://github.com/bellingcat/reddit-post-scraping-tool</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/bellingcat/reddit-post-scraping-tool</PackageProjectUrl>
|
||||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
<RepositoryUrl>https://github.com/bellingcat/reddit-post-scraping-tool</RepositoryUrl>
|
<RepositoryUrl>https://github.com/bellingcat/reddit-post-scraping-tool</RepositoryUrl>
|
||||||
<AssemblyVersion>1.7.0.0</AssemblyVersion>
|
<AssemblyVersion>1.8.0.0</AssemblyVersion>
|
||||||
<FileVersion>1.7.0.0</FileVersion>
|
<FileVersion>1.8.0.0</FileVersion>
|
||||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||||
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
|
||||||
<Version>1.7.0</Version>
|
<Version>1.8.0</Version>
|
||||||
<PackageTags>reddit;scraper;reddit-scraper;osint</PackageTags>
|
<PackageTags>reddit;scraper;reddit-scraper;osint</PackageTags>
|
||||||
<PackageReleaseNotes></PackageReleaseNotes>
|
<PackageReleaseNotes></PackageReleaseNotes>
|
||||||
<AnalysisLevel>6.0-recommended</AnalysisLevel>
|
<AnalysisLevel>6.0-recommended</AnalysisLevel>
|
||||||
|
|||||||
@@ -10,8 +10,10 @@ Public Class SettingsManager
|
|||||||
''' Indicates whether the dark mode is enabled or disabled.
|
''' Indicates whether the dark mode is enabled or disabled.
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Property DarkMode As Boolean
|
Public Property DarkMode As Boolean
|
||||||
|
Public Property SaveToJson As Boolean
|
||||||
|
Public Property SaveToCsv As Boolean
|
||||||
|
|
||||||
Private ReadOnly settingsFilePath As String = Path.Combine(Environment.CurrentDirectory, "settings.json")
|
Private ReadOnly settingsFilePath As String = Path.Combine(Environment.CurrentDirectory, "config.json")
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' Loads application settings from the 'settings.json' file.
|
''' Loads application settings from the 'settings.json' file.
|
||||||
@@ -23,34 +25,55 @@ Public Class SettingsManager
|
|||||||
If File.Exists(settingsFilePath) Then
|
If File.Exists(settingsFilePath) Then
|
||||||
Dim json As String = File.ReadAllText(settingsFilePath)
|
Dim json As String = File.ReadAllText(settingsFilePath)
|
||||||
Dim options As New JsonSerializerOptions With {.PropertyNameCaseInsensitive = True}
|
Dim options As New JsonSerializerOptions With {.PropertyNameCaseInsensitive = True}
|
||||||
Dim settings = Text.Json.JsonSerializer.Deserialize(Of SettingsManager)(json, options)
|
Dim settings = JsonSerializer.Deserialize(Of SettingsManager)(json, options)
|
||||||
Me.DarkMode = settings.DarkMode
|
|
||||||
FormMain.ToolStripMenuItemDarkMode.Checked = settings.DarkMode
|
DarkMode = settings.DarkMode
|
||||||
|
SaveToJson = settings.SaveToJson
|
||||||
|
SaveToCsv = settings.SaveToCsv
|
||||||
|
|
||||||
|
FormMain.DarkModeToolStripMenuItem.Checked = settings.DarkMode
|
||||||
|
FormMain.ToJSONToolStripMenuItem.Checked = settings.SaveToJson
|
||||||
|
FormMain.ToCSVToolStripMenuItem.Checked = settings.SaveToCsv
|
||||||
Else
|
Else
|
||||||
' Settings file does not exist
|
' Settings file does not exist
|
||||||
' Create a new file with default settings 'False'
|
' Create a new file with default settings 'False'
|
||||||
Dim defaultSettings = New SettingsManager With {.DarkMode = False}
|
Dim defaultSettings = New SettingsManager With {.DarkMode = False, .SaveToCsv = False, .SaveToJson = False}
|
||||||
Dim jsonOutput = Text.Json.JsonSerializer.Serialize(defaultSettings)
|
Dim jsonOutput = JsonSerializer.Serialize(defaultSettings)
|
||||||
File.WriteAllText(settingsFilePath, jsonOutput)
|
File.WriteAllText(settingsFilePath, jsonOutput)
|
||||||
|
|
||||||
Me.DarkMode = False
|
DarkMode = False
|
||||||
FormMain.ToolStripMenuItemDarkMode.Checked = False
|
SaveToJson = False
|
||||||
|
SaveToCsv = False
|
||||||
|
|
||||||
|
FormMain.ToJSONToolStripMenuItem.Checked = False
|
||||||
|
FormMain.ToCSVToolStripMenuItem.Checked = False
|
||||||
|
FormMain.DarkModeToolStripMenuItem.Checked = False
|
||||||
|
|
||||||
|
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' Toggles the Dark Mode setting on or off based on the provided parameter.
|
''' Retrieves application settings from a JSON file.
|
||||||
''' </summary>
|
''' </summary>
|
||||||
''' <param name="enabled">A Boolean indicating if Dark Mode should be enabled or not.</param>
|
''' <returns>A Dictionary containing the names and values of all settings.
|
||||||
Public Sub ToggleDarkMode(enabled As Boolean)
|
''' If the settings file doesn't exist, returns a Dictionary with default values.</returns>
|
||||||
Dim json As String = File.ReadAllText(settingsFilePath)
|
Private Function GetSettings() As Dictionary(Of String, Object)
|
||||||
Dim options As New JsonSerializerOptions With {.PropertyNameCaseInsensitive = True}
|
Dim settings As New Dictionary(Of String, Object)
|
||||||
Dim settings As SettingsManager = JsonSerializer.Deserialize(Of SettingsManager)(json, options)
|
If File.Exists(settingsFilePath) Then
|
||||||
settings.DarkMode = enabled
|
' Read and parse the JSON settings file.
|
||||||
SaveSettings(settings)
|
Dim json As String = File.ReadAllText(settingsFilePath)
|
||||||
ApplyTheme()
|
Dim jObject As JObject = JObject.Parse(json)
|
||||||
End Sub
|
|
||||||
|
' Loop through each property in the JObject and add it to the settings Dictionary.
|
||||||
|
For Each item As JProperty In jObject.Properties()
|
||||||
|
settings.Add(item.Name, item.Value.ToObject(Of Object)())
|
||||||
|
Next
|
||||||
|
Else
|
||||||
|
End If
|
||||||
|
Return settings
|
||||||
|
End Function
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' Saves the provided settings to the 'settings.json' file.
|
''' Saves the provided settings to the 'settings.json' file.
|
||||||
@@ -63,12 +86,20 @@ Public Class SettingsManager
|
|||||||
|
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' Applies the visual theme based on the Dark Mode setting.
|
''' Applies the current settings to the application's interface. This includes
|
||||||
''' If Dark Mode is enabled, a dark theme is applied. If it's disabled, a light theme is set.
|
''' toggling SaveToJson, SaveToCsv, and applying the visual theme based on the Dark Mode setting.
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Sub ApplyTheme()
|
Public Sub ApplySettings()
|
||||||
Dim DarkMode As Boolean = GetDarkMode()
|
' Retrieve the current settings
|
||||||
If DarkMode Then
|
Dim settings As Dictionary(Of String, Object) = GetSettings()
|
||||||
|
|
||||||
|
' Apply the SaveToJson setting to the menu item checkbox
|
||||||
|
FormMain.ToJSONToolStripMenuItem.Checked = CBool(settings("SaveToJson"))
|
||||||
|
|
||||||
|
' Apply the SaveToCsv setting to the menu item checkbox
|
||||||
|
FormMain.ToCSVToolStripMenuItem.Checked = CBool(settings("SaveToCsv"))
|
||||||
|
|
||||||
|
If CBool(settings("DarkMode")) Then
|
||||||
' Enable dark mode for the Main form
|
' Enable dark mode for the Main form
|
||||||
' Background colours (I know 'Colours'/'Colors'😆)
|
' Background colours (I know 'Colours'/'Colors'😆)
|
||||||
FormMain.BackColor = ColorTranslator.FromHtml("#FF121212")
|
FormMain.BackColor = ColorTranslator.FromHtml("#FF121212")
|
||||||
@@ -94,23 +125,25 @@ Public Class SettingsManager
|
|||||||
|
|
||||||
' Enable dark mode on 'Right Click Menu' items
|
' Enable dark mode on 'Right Click Menu' items
|
||||||
' Background colours
|
' Background colours
|
||||||
FormMain.ToolStripMenuItemDarkMode.BackColor = ColorTranslator.FromHtml("#FF121212")
|
FormMain.SettingsToolStripMenuItem.BackColor = ColorTranslator.FromHtml("#FF121212")
|
||||||
FormMain.ToolStripMenuItemSavePosts.BackColor = ColorTranslator.FromHtml("#FF121212")
|
FormMain.DarkModeToolStripMenuItem.BackColor = ColorTranslator.FromHtml("#FF121212")
|
||||||
FormMain.ToolStripMenuItemtoJSON.BackColor = ColorTranslator.FromHtml("#FF121212")
|
FormMain.SavePostsToolStripMenuItem.BackColor = ColorTranslator.FromHtml("#FF121212")
|
||||||
FormMain.ToolStripMenuItemtoCSV.BackColor = ColorTranslator.FromHtml("#FF121212")
|
FormMain.ToJSONToolStripMenuItem.BackColor = ColorTranslator.FromHtml("#FF121212")
|
||||||
FormMain.ToolStripMenuItemAbout.BackColor = ColorTranslator.FromHtml("#FF121212")
|
FormMain.ToCSVToolStripMenuItem.BackColor = ColorTranslator.FromHtml("#FF121212")
|
||||||
FormMain.ToolStripMenuItemDeveloper.BackColor = ColorTranslator.FromHtml("#FF121212")
|
FormMain.AboutToolStripMenuItem.BackColor = ColorTranslator.FromHtml("#FF121212")
|
||||||
FormMain.ToolStripMenuItemCheckUpdates.BackColor = ColorTranslator.FromHtml("#FF121212")
|
FormMain.DeveloperToolStripMenuItem.BackColor = ColorTranslator.FromHtml("#FF121212")
|
||||||
FormMain.ToolStripMenuItemQuit.BackColor = ColorTranslator.FromHtml("#FF121212")
|
FormMain.CheckForUpdatesToolStripMenuItem.BackColor = ColorTranslator.FromHtml("#FF121212")
|
||||||
|
FormMain.QuitToolStripMenuItem.BackColor = ColorTranslator.FromHtml("#FF121212")
|
||||||
' Foreground colours
|
' Foreground colours
|
||||||
FormMain.ToolStripMenuItemDarkMode.ForeColor = SystemColors.Control
|
FormMain.SettingsToolStripMenuItem.ForeColor = SystemColors.Control
|
||||||
FormMain.ToolStripMenuItemSavePosts.ForeColor = SystemColors.Control
|
FormMain.DarkModeToolStripMenuItem.ForeColor = SystemColors.Control
|
||||||
FormMain.ToolStripMenuItemtoJSON.ForeColor = SystemColors.Control
|
FormMain.SavePostsToolStripMenuItem.ForeColor = SystemColors.Control
|
||||||
FormMain.ToolStripMenuItemtoCSV.ForeColor = SystemColors.Control
|
FormMain.ToJSONToolStripMenuItem.ForeColor = SystemColors.Control
|
||||||
FormMain.ToolStripMenuItemAbout.ForeColor = SystemColors.Control
|
FormMain.ToCSVToolStripMenuItem.ForeColor = SystemColors.Control
|
||||||
FormMain.ToolStripMenuItemDeveloper.ForeColor = SystemColors.Control
|
FormMain.AboutToolStripMenuItem.ForeColor = SystemColors.Control
|
||||||
FormMain.ToolStripMenuItemCheckUpdates.ForeColor = SystemColors.Control
|
FormMain.DeveloperToolStripMenuItem.ForeColor = SystemColors.Control
|
||||||
FormMain.ToolStripMenuItemQuit.ForeColor = SystemColors.Control
|
FormMain.CheckForUpdatesToolStripMenuItem.ForeColor = SystemColors.Control
|
||||||
|
FormMain.QuitToolStripMenuItem.ForeColor = SystemColors.Control
|
||||||
|
|
||||||
|
|
||||||
' Enable dark mode for the About box
|
' Enable dark mode for the About box
|
||||||
@@ -123,10 +156,10 @@ Public Class SettingsManager
|
|||||||
AboutBox.LicenseRichTextBox.ForeColor = SystemColors.Control
|
AboutBox.LicenseRichTextBox.ForeColor = SystemColors.Control
|
||||||
AboutBox.LabelProgramName.ForeColor = SystemColors.Control
|
AboutBox.LabelProgramName.ForeColor = SystemColors.Control
|
||||||
AboutBox.LabelProgramDescription.ForeColor = SystemColors.Control
|
AboutBox.LabelProgramDescription.ForeColor = SystemColors.Control
|
||||||
AboutBox.LabelVersion.ForeColor = SystemColors.Control
|
AboutBox.LinkLabelVersion.ForeColor = SystemColors.Control
|
||||||
|
|
||||||
' If dark mode is enabled, set the 'Dark Mode' text value to 'Light mode'
|
' If dark mode is enabled, set the 'Dark Mode' text value to 'Light mode'
|
||||||
FormMain.ToolStripMenuItemDarkMode.Text = "Light Mode"
|
FormMain.DarkModeToolStripMenuItem.Text = "Dark Mode: Enabled"
|
||||||
Else
|
Else
|
||||||
' Disable dark mode for the Main Form
|
' Disable dark mode for the Main Form
|
||||||
' Background colours
|
' Background colours
|
||||||
@@ -152,23 +185,25 @@ Public Class SettingsManager
|
|||||||
|
|
||||||
' Disable dark mode on 'Right Click Menu' items
|
' Disable dark mode on 'Right Click Menu' items
|
||||||
' Background colours
|
' Background colours
|
||||||
FormMain.ToolStripMenuItemDarkMode.BackColor = Color.Gainsboro
|
FormMain.SettingsToolStripMenuItem.BackColor = Color.Gainsboro
|
||||||
FormMain.ToolStripMenuItemSavePosts.BackColor = Color.Gainsboro
|
FormMain.DarkModeToolStripMenuItem.BackColor = Color.Gainsboro
|
||||||
FormMain.ToolStripMenuItemtoJSON.BackColor = Color.Gainsboro
|
FormMain.SavePostsToolStripMenuItem.BackColor = Color.Gainsboro
|
||||||
FormMain.ToolStripMenuItemtoCSV.BackColor = Color.Gainsboro
|
FormMain.ToJSONToolStripMenuItem.BackColor = Color.Gainsboro
|
||||||
FormMain.ToolStripMenuItemAbout.BackColor = Color.Gainsboro
|
FormMain.ToCSVToolStripMenuItem.BackColor = Color.Gainsboro
|
||||||
FormMain.ToolStripMenuItemDeveloper.BackColor = Color.Gainsboro
|
FormMain.AboutToolStripMenuItem.BackColor = Color.Gainsboro
|
||||||
FormMain.ToolStripMenuItemCheckUpdates.BackColor = Color.Gainsboro
|
FormMain.DeveloperToolStripMenuItem.BackColor = Color.Gainsboro
|
||||||
FormMain.ToolStripMenuItemQuit.BackColor = Color.Gainsboro
|
FormMain.CheckForUpdatesToolStripMenuItem.BackColor = Color.Gainsboro
|
||||||
|
FormMain.QuitToolStripMenuItem.BackColor = Color.Gainsboro
|
||||||
' Foreground colours
|
' Foreground colours
|
||||||
FormMain.ToolStripMenuItemDarkMode.ForeColor = Color.Black
|
FormMain.SettingsToolStripMenuItem.ForeColor = Color.Black
|
||||||
FormMain.ToolStripMenuItemSavePosts.ForeColor = Color.Black
|
FormMain.DarkModeToolStripMenuItem.ForeColor = Color.Black
|
||||||
FormMain.ToolStripMenuItemtoJSON.ForeColor = Color.Black
|
FormMain.SavePostsToolStripMenuItem.ForeColor = Color.Black
|
||||||
FormMain.ToolStripMenuItemtoCSV.ForeColor = Color.Black
|
FormMain.ToJSONToolStripMenuItem.ForeColor = Color.Black
|
||||||
FormMain.ToolStripMenuItemAbout.ForeColor = Color.Black
|
FormMain.ToCSVToolStripMenuItem.ForeColor = Color.Black
|
||||||
FormMain.ToolStripMenuItemDeveloper.ForeColor = Color.Black
|
FormMain.AboutToolStripMenuItem.ForeColor = Color.Black
|
||||||
FormMain.ToolStripMenuItemCheckUpdates.ForeColor = Color.Black
|
FormMain.DeveloperToolStripMenuItem.ForeColor = Color.Black
|
||||||
FormMain.ToolStripMenuItemQuit.ForeColor = Color.Black
|
FormMain.CheckForUpdatesToolStripMenuItem.ForeColor = Color.Black
|
||||||
|
FormMain.QuitToolStripMenuItem.ForeColor = Color.Black
|
||||||
|
|
||||||
' Disable dark mode for the About box
|
' Disable dark mode for the About box
|
||||||
' Background colours
|
' Background colours
|
||||||
@@ -181,26 +216,39 @@ Public Class SettingsManager
|
|||||||
AboutBox.Panel1.ForeColor = SystemColors.WindowText
|
AboutBox.Panel1.ForeColor = SystemColors.WindowText
|
||||||
AboutBox.LabelProgramName.ForeColor = SystemColors.WindowText
|
AboutBox.LabelProgramName.ForeColor = SystemColors.WindowText
|
||||||
AboutBox.LabelProgramDescription.ForeColor = SystemColors.WindowText
|
AboutBox.LabelProgramDescription.ForeColor = SystemColors.WindowText
|
||||||
AboutBox.LabelVersion.ForeColor = SystemColors.WindowText
|
AboutBox.LinkLabelVersion.ForeColor = SystemColors.WindowText
|
||||||
|
|
||||||
' If dark mode is disabled, set the 'Light Mode' text value to 'Dark Mode'
|
' If dark mode is disabled, set the 'Light Mode' text value to 'Dark Mode'
|
||||||
FormMain.ToolStripMenuItemDarkMode.Text = "Dark Mode"
|
FormMain.DarkModeToolStripMenuItem.Text = "Dark Mode: Disabled"
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' Retrieves the Dark Mode setting value from 'settings.json'.
|
''' Toggles specific settings on or off based on the provided parameters.
|
||||||
''' If the settings file doesn't exist, defaults to returning 'False' (Dark Mode off).
|
|
||||||
''' </summary>
|
''' </summary>
|
||||||
''' <returns>A Boolean indicating if Dark Mode is enabled or not.</returns>
|
''' <param name="enabled">A Boolean indicating if the setting option should be enabled or not.</param>
|
||||||
Private Function GetDarkMode() As Boolean
|
''' <param name="saveTo">A String specifying the type of setting to toggle ('json', 'csv', or 'darkmode').</param>
|
||||||
If File.Exists(settingsFilePath) Then
|
Public Sub ToggleSettings(enabled As Boolean, saveTo As String)
|
||||||
Dim json As String = File.ReadAllText(settingsFilePath)
|
' Read the existing settings from the settings file
|
||||||
Dim settings As JObject = JObject.Parse(json)
|
Dim json As String = File.ReadAllText(settingsFilePath)
|
||||||
Return settings(NameOf(DarkMode)).ToObject(Of Boolean)()
|
Dim options As New JsonSerializerOptions With {.PropertyNameCaseInsensitive = True}
|
||||||
|
Dim settings As SettingsManager = JsonSerializer.Deserialize(Of SettingsManager)(json, options)
|
||||||
|
|
||||||
|
' Update the settings based on the specified saveTo parameter
|
||||||
|
If saveTo.ToLower(Globalization.CultureInfo.InvariantCulture) = "json" Then
|
||||||
|
settings.SaveToJson = enabled
|
||||||
|
ElseIf saveTo.ToLower(Globalization.CultureInfo.InvariantCulture) = "csv" Then
|
||||||
|
settings.SaveToCsv = enabled
|
||||||
|
ElseIf saveTo.ToLower(Globalization.CultureInfo.InvariantCulture) = "darkmode" Then
|
||||||
|
settings.DarkMode = enabled
|
||||||
Else
|
Else
|
||||||
Return False
|
' Handle unexpected value of saveTo (if needed)
|
||||||
End If
|
End If
|
||||||
End Function
|
|
||||||
|
' Save the updated settings back to the settings file
|
||||||
|
SaveSettings(settings)
|
||||||
|
' Apply the updated settings to the application
|
||||||
|
ApplySettings()
|
||||||
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
@@ -3,54 +3,6 @@ Imports Newtonsoft.Json
|
|||||||
Imports Newtonsoft.Json.Linq
|
Imports Newtonsoft.Json.Linq
|
||||||
|
|
||||||
Public Class Utilities
|
Public Class Utilities
|
||||||
''' <summary>
|
|
||||||
''' Collects user inputs, fetches Reddit posts based on the inputs, checks if posts contain the keyword, and saves posts to a JSON file if necessary.
|
|
||||||
''' </summary>
|
|
||||||
''' <param name="JSONToolStripMenuItem">Indicates whether to save the posts to a JSON file.</param>
|
|
||||||
''' <remarks>
|
|
||||||
''' This function initializes the DataGridView, iterates over each post, adds the posts containing the keyword to the DataGridView and updates the UI.
|
|
||||||
''' It also shows a message if the keyword was not found in any of the posts or if the inputs are empty.
|
|
||||||
''' </remarks>
|
|
||||||
Public Shared Sub ProcessRedditPosts(JSONToolStripMenuItem As ToolStripMenuItem)
|
|
||||||
' Collect inputs from the user
|
|
||||||
Dim inputs = CollectInputs()
|
|
||||||
|
|
||||||
If inputs.HasValue Then
|
|
||||||
' Initialize the DataGridView
|
|
||||||
DataGridViewHandler.AddColumn(FormPosts.DataGridViewPosts)
|
|
||||||
|
|
||||||
' Fetch Reddit posts based on the inputs
|
|
||||||
Dim processor As New PostsProcessor()
|
|
||||||
Dim posts As JObject = processor.FetchPosts(inputs.Value.Subreddit, inputs.Value.Listing, inputs.Value.Limit, inputs.Value.Timeframe)
|
|
||||||
Dim totalPosts As Integer = 0
|
|
||||||
Dim keywordFound As Boolean = False
|
|
||||||
|
|
||||||
' Iterate over each post
|
|
||||||
For Each post In posts("data")("children")
|
|
||||||
totalPosts += 1
|
|
||||||
' Check if the post contains the keyword
|
|
||||||
If PostsProcessor.PostContainsKeyword(post, inputs.Value.Keyword.ToLower(Globalization.CultureInfo.InvariantCulture)) Then
|
|
||||||
' Add the post to the DataGridView
|
|
||||||
DataGridViewHandler.AddRow(FormPosts.DataGridViewPosts, post, totalPosts)
|
|
||||||
FormPosts.Show()
|
|
||||||
keywordFound = True
|
|
||||||
End If
|
|
||||||
Next
|
|
||||||
|
|
||||||
' Check if the keyword was found in any posts
|
|
||||||
If Not keywordFound Then
|
|
||||||
MessageBox.Show($"Keyword `{inputs.Value.Keyword}` was not found in any of the " + posts("data")("children").Count.ToString(Globalization.CultureInfo.InvariantCulture) _
|
|
||||||
+ $" {inputs.Value.Listing} posts from r/{inputs.Value.Subreddit}", "Not Found", MessageBoxButtons.OK, MessageBoxIcon.Warning)
|
|
||||||
End If
|
|
||||||
|
|
||||||
If JSONToolStripMenuItem.Checked Then
|
|
||||||
' Save posts to a JSON file if the JSONToolStripMenuItem is checked
|
|
||||||
Utilities.SavePostsToJson(posts("data"))
|
|
||||||
End If
|
|
||||||
Else
|
|
||||||
End If
|
|
||||||
End Sub
|
|
||||||
|
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' Checks for the existence of the 'logs' directory under the 'RPST' directory within the user's AppData\Roaming folder.
|
''' Checks for the existence of the 'logs' directory under the 'RPST' directory within the user's AppData\Roaming folder.
|
||||||
@@ -87,14 +39,18 @@ Public Class Utilities
|
|||||||
Public Shared Function CollectInputs() As (Keyword As String, Subreddit As String, Listing As String, Limit As Integer, Timeframe As String)?
|
Public Shared Function CollectInputs() As (Keyword As String, Subreddit As String, Listing As String, Limit As Integer, Timeframe As String)?
|
||||||
Dim keyword As String = FormMain.TextBoxKeyword.Text.Trim()
|
Dim keyword As String = FormMain.TextBoxKeyword.Text.Trim()
|
||||||
Dim subreddit As String = FormMain.TextBoxSubreddit.Text.Trim()
|
Dim subreddit As String = FormMain.TextBoxSubreddit.Text.Trim()
|
||||||
' Convert the Listing and Subreddit to lowercase using InvariantCulture
|
''' <summary>
|
||||||
|
''' Convert the Listing and Subreddit to lowercase using InvariantCulture.
|
||||||
|
''' <summary>
|
||||||
Dim listing As String = If(String.IsNullOrEmpty(FormMain.ComboBoxListing.Text), "top", FormMain.ComboBoxListing.Text.ToLower(Globalization.CultureInfo.InvariantCulture).Trim())
|
Dim listing As String = If(String.IsNullOrEmpty(FormMain.ComboBoxListing.Text), "top", FormMain.ComboBoxListing.Text.ToLower(Globalization.CultureInfo.InvariantCulture).Trim())
|
||||||
Dim timeframe As String = If(String.IsNullOrEmpty(FormMain.ComboBoxTimeframe.Text), "all", FormMain.ComboBoxTimeframe.Text.ToLower(Globalization.CultureInfo.InvariantCulture).Trim())
|
Dim timeframe As String = If(String.IsNullOrEmpty(FormMain.ComboBoxTimeframe.Text), "all", FormMain.ComboBoxTimeframe.Text.ToLower(Globalization.CultureInfo.InvariantCulture).Trim())
|
||||||
Dim limit As Integer = FormMain.NumericUpDownLimit.Value
|
Dim limit As Integer = FormMain.NumericUpDownLimit.Value
|
||||||
|
|
||||||
' Validate inputs
|
''' <summary>
|
||||||
|
''' Validate inputs.
|
||||||
|
''' <summary>
|
||||||
If String.IsNullOrEmpty(keyword) AndAlso String.IsNullOrEmpty(subreddit) Then
|
If String.IsNullOrEmpty(keyword) AndAlso String.IsNullOrEmpty(subreddit) Then
|
||||||
MessageBox.Show("Keyword and Subreddit fields should not be empty.", "Invalid Inputs", MessageBoxButtons.OK, MessageBoxIcon.Warning)
|
MessageBox.Show("Keyword and Subreddit should not be empty.", "Invalid Inputs", MessageBoxButtons.OK, MessageBoxIcon.Warning)
|
||||||
Return Nothing
|
Return Nothing
|
||||||
ElseIf String.IsNullOrEmpty(keyword) Then
|
ElseIf String.IsNullOrEmpty(keyword) Then
|
||||||
MessageBox.Show("Keyword field should not be empty.", "Invalid Input", MessageBoxButtons.OK, MessageBoxIcon.Warning)
|
MessageBox.Show("Keyword field should not be empty.", "Invalid Input", MessageBoxButtons.OK, MessageBoxIcon.Warning)
|
||||||
@@ -137,6 +93,42 @@ Public Class Utilities
|
|||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
|
|
||||||
|
''' <summary>
|
||||||
|
''' Saves Reddit posts contained in a JArray to a CSV file.
|
||||||
|
''' </summary>
|
||||||
|
''' <param name="posts">A JArray containing the Reddit posts to be saved.</param>
|
||||||
|
''' <remarks>
|
||||||
|
''' This function displays a SaveFileDialog to allow the user to specify the file name and location.
|
||||||
|
''' It then iterates through the JArray to write each post's details (totalPosts, title, subreddit, author, score) into the selected CSV file.
|
||||||
|
''' </remarks>
|
||||||
|
Public Shared Sub SavePostsToCSV(posts As JArray)
|
||||||
|
Dim saveFileDialog As New SaveFileDialog With {
|
||||||
|
.Filter = "CSV files (*.csv)|*.csv",
|
||||||
|
.Title = "Save posts to CSV"
|
||||||
|
}
|
||||||
|
|
||||||
|
If saveFileDialog.ShowDialog() = DialogResult.OK Then
|
||||||
|
Dim fileName As String = saveFileDialog.FileName
|
||||||
|
Using csvWriter As New StreamWriter(fileName)
|
||||||
|
''' <summary>
|
||||||
|
''' Write the header.
|
||||||
|
''' <summary>
|
||||||
|
csvWriter.WriteLine("Index,Author,ID,Subreddit,Visibility,Thumbnail,NSFW,Gilded,Upvotes,Upvote Ratio,Downvotes,Award,Top Award,Is cross-postable?,Score,Category,Text,Domain,Permalink,Created At,Approved At,Approved By")
|
||||||
|
|
||||||
|
Dim postCount As Integer = 0
|
||||||
|
For Each post In posts
|
||||||
|
postCount += 1
|
||||||
|
csvWriter.WriteLine($"{postCount},{post("data")("author")},{post("data")("id")},{post("data")("subreddit_name_prefixed")},{post("data")("subreddit_type")},{post("data")("thumbnail")},{post("data")("over_18")},{post("data")("gilded")},{post("data")("ups")},{post("data")("upvote_ratio")},{post("data")("downs")},{post("data")("total_awards_received")},{post("data")("top_awarded_type")},{post("data")("is_crosspostable")},{post("data")("score")},{post("data")("category")},{post("data")("selftext")},{post("data")("domain")},{post("data")("permalink")},{post("data")("created")},{post("data")("approved_at_utc")},{post("data")("approved_by")}")
|
||||||
|
Next
|
||||||
|
End Using
|
||||||
|
|
||||||
|
MessageBox.Show($"Posts saved to {fileName}", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information)
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' Shows the license notice in a messagebox.
|
''' Shows the license notice in a messagebox.
|
||||||
''' </summary>
|
''' </summary>
|
||||||
|
|||||||
BIN
images/2023-08-08_07-04.png
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
images/2023-08-08_07-04_1.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
images/2023-08-08_07-12.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
images/2023-08-08_07-12_1.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
images/2023-08-25_15-30.png
Normal file
|
After Width: | Height: | Size: 576 KiB |
BIN
images/2023-08-25_15-31.png
Normal file
|
After Width: | Height: | Size: 519 KiB |
BIN
images/2023-08-25_15-35.png
Normal file
|
After Width: | Height: | Size: 823 KiB |
BIN
images/2023-08-25_15-39.png
Normal file
|
After Width: | Height: | Size: 508 KiB |
BIN
images/2023-08-30_03-11.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
images/2023-08-30_03-12.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
@@ -7,7 +7,7 @@ packages = ["rpst"]
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "reddit-post-scraping-tool"
|
name = "reddit-post-scraping-tool"
|
||||||
version = "1.7.0.0"
|
version = "1.8.0.0"
|
||||||
description = "Given a subreddit name and a keyword, RPST returns all top (by default) posts that contain the specified keyword."
|
description = "Given a subreddit name and a keyword, RPST returns all top (by default) posts that contain the specified keyword."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.8"
|
requires-python = ">=3.8"
|
||||||
|
|||||||
@@ -14,20 +14,20 @@ def run():
|
|||||||
parser = create_parser()
|
parser = create_parser()
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
log = set_loglevel(args=args)
|
log = set_loglevel(debug_mode=args.debug)
|
||||||
|
|
||||||
# Record the start time
|
# Record the start time
|
||||||
start_time = datetime.now()
|
start_time = datetime.now()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Check for updates
|
# Check for updates
|
||||||
check_updates(version_tag="1.7.0.0")
|
check_updates(version_tag="1.8.0.0")
|
||||||
|
|
||||||
# Get posts with the provided/parsed arguments
|
# Get posts with the provided/parsed arguments
|
||||||
get_posts(args=args)
|
get_posts(args=args)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
log.warning("User interruption detected.")
|
log.warning("User interruption detected ([yellow]Ctrl+C[/]).")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error(f"An error occurred: {e}")
|
log.error(f"An error occurred: [red]{e}[/]")
|
||||||
finally:
|
finally:
|
||||||
log.info(f"Finished in {datetime.now() - start_time} seconds.")
|
log.info(f"Finished in {datetime.now() - start_time} seconds.")
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ from datetime import datetime
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
from glyphoji import glyph
|
from glyphoji import glyph
|
||||||
|
from rich import print
|
||||||
from rich.tree import Tree
|
from rich.tree import Tree
|
||||||
from rich import print as xprint
|
|
||||||
|
|
||||||
from .utils import convert_timestamp_to_datetime, write_post_data
|
from .utils import convert_timestamp_to_datetime, write_post_data
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ def create_post_branch(post: dict, keyword: str, tree: Tree, args: argparse) ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Add the post's branch to the main tree.
|
# Add the post's branch to the main tree.
|
||||||
post_branch = tree.add(f"{glyph.scroll} {post['data']['title']}")
|
post_branch = tree.add(f"{glyph.page_with_curl} {post['data']['title']}")
|
||||||
|
|
||||||
# Add each piece of extracted data as a branch of the post_branch.
|
# Add each piece of extracted data as a branch of the post_branch.
|
||||||
for post_key, post_value in post_data.items():
|
for post_key, post_value in post_data.items():
|
||||||
@@ -128,4 +128,4 @@ def get_posts(args: argparse):
|
|||||||
f"{glyph.check_mark_button} Keyword ('{keyword}') was found in "
|
f"{glyph.check_mark_button} Keyword ('{keyword}') was found in "
|
||||||
f"{found_posts}/{len(response['data']['children'])} {listing} posts from r/{subreddit}."
|
f"{found_posts}/{len(response['data']['children'])} {listing} posts from r/{subreddit}."
|
||||||
)
|
)
|
||||||
xprint(main_tree)
|
print(main_tree)
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ from datetime import datetime
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
from glyphoji import glyph
|
from glyphoji import glyph
|
||||||
|
from rich import print
|
||||||
from rich.tree import Tree
|
from rich.tree import Tree
|
||||||
from rich import print as xprint
|
|
||||||
from rich.markdown import Markdown
|
from rich.markdown import Markdown
|
||||||
from rich.logging import RichHandler
|
from rich.logging import RichHandler
|
||||||
|
|
||||||
@@ -84,7 +85,7 @@ def create_parser():
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-d",
|
"-d",
|
||||||
"--debug",
|
"--debug",
|
||||||
help="run rpst in debug mode (show network logs)",
|
help="run rpst in debug mode",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -110,50 +111,30 @@ def check_updates(version_tag: str):
|
|||||||
raw_release_notes = response["body"]
|
raw_release_notes = response["body"]
|
||||||
|
|
||||||
# Log an info message about the new release.
|
# Log an info message about the new release.
|
||||||
xprint(
|
print(
|
||||||
f"{glyph.up_arrow} A new release of RPST is available ({response['tag_name']}). "
|
f"{glyph.up_arrow} A new release of RPST is available ({response['tag_name']}). "
|
||||||
f"Run 'pip install --upgrade reddit-post-scraping-tool' to get the updates."
|
f"Run 'pip install --upgrade reddit-post-scraping-tool' to get the updates."
|
||||||
)
|
)
|
||||||
|
|
||||||
# Print the release notes.
|
# Print the release notes.
|
||||||
xprint(Markdown(raw_release_notes))
|
print(Markdown(raw_release_notes))
|
||||||
|
|
||||||
|
|
||||||
def set_loglevel(args: argparse) -> logging.getLogger:
|
def set_loglevel(debug_mode: bool) -> logging.getLogger:
|
||||||
"""
|
"""
|
||||||
Configures the logging level based on the provided arguments.
|
Configure and return a logging object with the specified log level.
|
||||||
|
|
||||||
If `args.debug` is True, the logging level is set to "NOTSET," allowing all log messages to be displayed.
|
:param debug_mode: If True, the log level is set to "NOTSET". Otherwise, it is set to "INFO".
|
||||||
Otherwise, the logging level is set to "INFO," and only informational and higher-severity messages are displayed.
|
:return: A logging object configured with the specified log level.
|
||||||
|
|
||||||
The function also configures a RichHandler for formatting the log messages,
|
|
||||||
including a specific time format and hiding the log level.
|
|
||||||
|
|
||||||
:param args: A namespace object from argparse containing the debugging option (args.debug).
|
|
||||||
:return: A logger object associated with the name "rich."
|
|
||||||
"""
|
"""
|
||||||
if args.debug:
|
logging.basicConfig(
|
||||||
logging.basicConfig(
|
level="NOTSET" if debug_mode else "INFO",
|
||||||
level="NOTSET",
|
format="%(message)s",
|
||||||
format="%(message)s",
|
handlers=[
|
||||||
handlers=[
|
RichHandler(markup=True, log_time_format="[%I:%M:%S %p]", show_level=False)
|
||||||
RichHandler(
|
],
|
||||||
markup=True, log_time_format="[%H:%M:%S%p]", show_level=False
|
)
|
||||||
)
|
return logging.getLogger("RPST")
|
||||||
],
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
logging.basicConfig(
|
|
||||||
level="INFO",
|
|
||||||
format="%(message)s",
|
|
||||||
handlers=[
|
|
||||||
RichHandler(
|
|
||||||
markup=True, log_time_format="[%H:%M:%S%p]", show_level=False
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
return logging.getLogger("rich")
|
|
||||||
|
|
||||||
|
|
||||||
def write_post_data(post_data: dict, filename: str, args, tree_branch: Tree):
|
def write_post_data(post_data: dict, filename: str, args, tree_branch: Tree):
|
||||||
|
|||||||