52 Commits

Author SHA1 Message Date
Miguel Sozinho Ramalho
f8c25a3cef Update README.md 2023-12-22 13:31:11 +00:00
Richard Mwewa
d73ffd8acb Update __init__.py 2023-12-03 21:32:33 +02:00
Richard Mwewa
1a95af33ea Update pyproject.toml 2023-12-03 21:32:08 +02:00
Richard Mwewa
1dfefd9ef1 Update README.md 2023-12-03 21:31:47 +02:00
Richard Mwewa
7d5894224b Delete RPST GUI/RPST/ApiHandler.vb 2023-12-03 18:57:08 +00:00
Richard Mwewa
981fbfcac1 Add files via upload 2023-12-03 18:55:21 +00:00
Richard Mwewa
145d33ef9e Add files via upload 2023-12-03 18:54:23 +00:00
Richard Mwewa
c544ede53b Delete RPST GUI/RPST directory 2023-12-03 20:50:29 +02:00
Richard Mwewa
1c2d114b0e Delete rpst/rpst.py 2023-12-03 20:49:36 +02:00
Richard Mwewa
5dbc752056 Merge pull request #21 from bellingcat/dev
Dev
2023-12-03 20:49:18 +02:00
rly0nheart
4ae45320c7 Resolve conflict 2023-12-03 20:47:27 +02:00
rly0nheart
c25d3942ec Added setup project for easy installation. Scraping more than 100 posts. Fully Async. Major code improvements and optimisations 2023-12-03 18:37:13 +00:00
rly0nheart
6611cc2023 Update 2023-12-03 18:35:46 +00:00
rly0nheart
9abc351ffa Added setup project for easy installation. Scraping more than 100 posts. Fully Async. Major code improvements and optimisations 2023-12-03 18:32:10 +00:00
rly0nheart
f92efe640e Update rpst 2023-12-03 18:14:51 +02:00
rly0nheart
68253a6986 Update README.md 2023-12-03 18:12:04 +02:00
Richard Mwewa
1cf78c3609 Update README.md 2023-12-03 17:52:16 +02:00
rly0nheart
ff905764cf Scraping more than 100 posts. Code refactor and optimisation. Improved the file writer and update checker functions 2023-12-03 17:39:32 +02:00
Richard Mwewa
76a6dec671 Merge pull request #20 from bellingcat/galen-endpoint-fix
Add subdomain to Reddit endpoint to avoid redirect
2023-11-30 15:59:07 +02:00
Galen Reich
10fa0688a5 Add explicit www. to api endpoint 2023-11-30 11:32:45 +00:00
Galen Reich
ad547b4eaf Add explicit www. to reddit endpoint 2023-11-30 11:32:05 +00:00
Richard Mwewa
00688ea0e4 Merge pull request #19 from bellingcat/dev
Dev
2023-10-19 01:17:33 +02:00
Richard Mwewa
6dd075a44e Update README.md 2023-10-19 01:15:42 +02:00
Richard Mwewa
dd4d10df57 Update README.md 2023-10-19 01:15:10 +02:00
Richard Mwewa
a1ab71b205 Update README.md 2023-10-19 01:14:33 +02:00
Richard Mwewa
61be692c4e Update RPST.vbproj 2023-10-19 01:13:46 +02:00
Richard Mwewa
e54b0f24e0 Update main.py 2023-10-16 19:54:13 +02:00
Richard Mwewa
7c4e1a8a38 Update pyproject.toml 2023-10-16 19:53:12 +02:00
Richard Mwewa
21d176f7b0 Update README.md 2023-10-16 19:49:41 +02:00
Richard Mwewa
e5386f89b1 Update dependabot.yml 2023-09-25 18:40:21 +02:00
Richard Mwewa
e904570117 Create FUNDING.yml 2023-09-25 18:39:04 +02:00
Richard Mwewa
7961cd05fe Update README.md 2023-09-01 14:36:14 +02:00
Richard Mwewa
26b08980e9 Update Utilities.vb 2023-08-31 22:52:51 +02:00
Richard Mwewa
6c47e5609e Add files via upload 2023-08-31 22:13:57 +02:00
Richard Mwewa
b96889f078 Update main.py 2023-08-31 22:04:57 +02:00
Richard Mwewa
2dca02e315 Update pyproject.toml 2023-08-31 22:04:29 +02:00
Richard Mwewa
23553a3d34 Merge pull request #18 from bellingcat/dev
Add files via upload
2023-08-31 22:02:27 +02:00
Richard Mwewa
2441197a5f Add files via upload 2023-08-31 21:55:29 +02:00
Richard Mwewa
6db8af96c4 Merge pull request #17 from bellingcat/dev
Dev
2023-08-31 21:02:41 +02:00
Richard Mwewa
07a6031394 Update README.md 2023-08-31 21:01:48 +02:00
Richard Mwewa
246c0d9943 Update README.md 2023-08-31 20:59:47 +02:00
Richard Mwewa
ec5e84e3bb Add files via upload 2023-08-31 20:58:06 +02:00
Richard Mwewa
4eaaaf5764 Delete RPST GUI directory 2023-08-31 20:55:42 +02:00
Richard Mwewa
5685dc9734 Delete RPST GUI/RPST/DeveloperBox.resx 2023-08-31 20:55:08 +02:00
Richard Mwewa
fba1b65d4e Delete RPST GUI/RPST/DeveloperBox.Designer.vb 2023-08-31 20:54:56 +02:00
Richard Mwewa
25fec049f8 Merge pull request #16 from bellingcat/dev
Dev
2023-08-31 20:49:46 +02:00
Richard Mwewa
d920dad7a8 Update README.md 2023-08-31 20:48:29 +02:00
Richard Mwewa
83ac5d710c dev 1.9.0.0 2023-08-31 20:47:28 +02:00
Richard Mwewa
ceccd434b4 dev 1.9.0.0 2023-08-31 20:46:36 +02:00
Richard Mwewa
156482eb68 Update main.py 2023-08-31 20:44:29 +02:00
Richard Mwewa
782eb1577f dev 1.9.0.0 2023-08-31 20:43:52 +02:00
Richard Mwewa
0023a974fc dev 1.9.0.0 2023-08-31 20:43:00 +02:00
60 changed files with 5999 additions and 4673 deletions

13
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: ['https://buymeacoffee.com/_rly0nheart'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

View File

@@ -8,7 +8,7 @@ updates:
- package-ecosystem: "nuget"
schedule:
interval: "daily"
directory: "RPST GUI"
directory: "Knew Karma"
ignore:
- dependency-name: "Newtonsoft.Json"
- package-ecosystem: "pip"

View File

@@ -1,42 +1,47 @@
# RPST (Reddit Post Scraping Tool)
Given a subreddit name and a keyword, RPST will return all posts from a specified listing (default is 'top') that contain the provided keyword.
[![Upload Python Package](https://github.com/bellingcat/reddit-post-scraping-tool/actions/workflows/python-publish.yml/badge.svg)](https://github.com/rly0nheart/reddit-post-scraping-tool/actions/workflows/python-publish.yml) [![CodeQL](https://github.com/bellingcat/reddit-post-scraping-tool/actions/workflows/codeql.yml/badge.svg)](https://github.com/rly0nheart/reddit-post-scraping-tool/actions/workflows/codeql.yml) ![.Net](https://img.shields.io/badge/.NET-5C2D91?style=flat&logo=.net&logoColor=white) ![Python](https://img.shields.io/badge/python-3670A0?style=flat&logo=python&logoColor=ffdd54)
## Note
> Use [Knew Karma](https://pypi.org/project/knewkarma) for more advanced and improved features.
![rpst](https://github.com/bellingcat/reddit-post-scraping-tool/assets/74001397/b9ec50b2-d2cb-419f-b8f0-d170b0630875)
# RPST (Reddit Post Scraping Tool)
Retrieve **Reddit** posts that contain the specified **keyword** from a specified **subreddit**.
[![.Net](https://img.shields.io/badge/Visual%20Basic%20.NET-5C2D91?style=flat&logo=.net&logoColor=white)](https://github.com/search?q=repo%3Abellingcat%2Freddit-post-scraping-tool++language%3A%22Visual+Basic+.NET%22&type=code) [![Python](https://img.shields.io/badge/Python-3670A0?style=flat&logo=python&logoColor=ffdd54)](https://github.com/search?q=repo%3Abellingcat%2Freddit-post-scraping-tool++language%3APython&type=code) [![Docker](https://img.shields.io/badge/Dockefile-%230db7ed.svg?style=flat&logo=docker&logoColor=white)](https://github.com/search?q=repo%3Abellingcat%2Freddit-post-scraping-tool++language%3ADockerfile&type=code) [![PyPI - Version](https://img.shields.io/pypi/v/reddit-post-scraping-tool?style=flat&logo=pypi&logoColor=ffdd54&label=PyPI&labelColor=3670A0&color=3670A0)](https://pypi.org/project/reddit-post-scraping-tool) [![BuyMeACoffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-ffdd00?style=flat&logo=buy-me-a-coffee&logoColor=black)](https://buymeacoffee.com/_rly0nheart)
# ✅ Features
## *GUI*
- [x] Dark mode (*Right-click*).
- [x] Saves results to a JSON file (*Right-click*).
- [x] Dark mode (*Right-click>Settings>Dark Mode*).
- [x] Saves results to a JSON/CSV file (*Right-click>Settings>Save posts>to JSON/to CSV*).
- [x] Logs errors to a file.
- [x] In-App feature to check for Updates.
## *CLI*
- [x] Saves results to JSON (*specifiy* `--json`).
- [x] Saves results to CSV (*specify* `--csv`).
- [x] Automatically checks for new updates, and notifies user if updates were found.
# 📃 TODO
## *GUI*
- [ ] Make it installable with a setup.exe/setup.msi file.
- [x] Add manual dark mode option, that will be persistent in all sessions.
- [x] Make settings persistent in all sessions.
- [x] Make it save results to a CSV file.
# 🖥️ Tested environments
## *GUI*
- [x] Microsoft Windows 11
## *CLI*
- [x] Android Termux
- [x] Microsoft Windows 11
- [x] Ubuntu 22.04 - latest versions
# 📖 Wiki
[Refer to the Wiki](https://github.com/bellingcat/reddit-post-scraping-tool/wiki) for installation instructions, in addition to all other documentation.
# 📖 Documentation
[Refer to the Wiki](https://github.com/bellingcat/reddit-post-scraping-tool/wiki) for installation instructions, in
addition to all other documentation.
# 🖼️ Screenshots
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>
![me](https://github.com/bellingcat/reddit-post-scraping-tool/assets/74001397/21e0bb33-7a84-45d6-92ba-00e40891ba31)
[![me](https://github.com/bellingcat/knewkarma/assets/74001397/efd19c7e-9840-4969-b33c-04087e73e4da)](https://about.me/rly0nheart)

View File

@@ -5,6 +5,8 @@ VisualStudioVersion = 17.4.33213.308
MinimumVisualStudioVersion = 10.0.40219.1
Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "RPST", "RPST\RPST.vbproj", "{46C2541E-6F65-461A-A479-F65D445C36EA}"
EndProject
Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "RPSTSetup", "RPSTSetup\RPSTSetup.vdproj", "{7D89A26E-2D54-4BB7-B9C4-E1382E657DEA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -15,6 +17,8 @@ Global
{46C2541E-6F65-461A-A479-F65D445C36EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{46C2541E-6F65-461A-A479-F65D445C36EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{46C2541E-6F65-461A-A479-F65D445C36EA}.Release|Any CPU.Build.0 = Release|Any CPU
{7D89A26E-2D54-4BB7-B9C4-E1382E657DEA}.Debug|Any CPU.ActiveCfg = Debug
{7D89A26E-2D54-4BB7-B9C4-E1382E657DEA}.Release|Any CPU.ActiveCfg = Release
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -1,143 +0,0 @@
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class AboutBox
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Dim resources As ComponentModel.ComponentResourceManager = New ComponentModel.ComponentResourceManager(GetType(AboutBox))
PictureBoxLogo = New PictureBox()
LabelProgramName = New Label()
LabelProgramDescription = New Label()
LinkLabelReadtheWiki = New LinkLabel()
Panel1 = New Panel()
LinkLabelVersion = New LinkLabel()
LicenseRichTextBox = New RichTextBox()
CType(PictureBoxLogo, ComponentModel.ISupportInitialize).BeginInit()
Panel1.SuspendLayout()
SuspendLayout()
'
' PictureBoxLogo
'
PictureBoxLogo.BackColor = Color.Transparent
PictureBoxLogo.Image = CType(resources.GetObject("PictureBoxLogo.Image"), Image)
PictureBoxLogo.Location = New Point(12, 12)
PictureBoxLogo.Name = "PictureBoxLogo"
PictureBoxLogo.Size = New Size(88, 93)
PictureBoxLogo.SizeMode = PictureBoxSizeMode.StretchImage
PictureBoxLogo.TabIndex = 0
PictureBoxLogo.TabStop = False
'
' LabelProgramName
'
LabelProgramName.AutoSize = True
LabelProgramName.Font = New Font("Segoe Script", 9.75F, FontStyle.Bold, GraphicsUnit.Point)
LabelProgramName.ForeColor = SystemColors.ControlText
LabelProgramName.Location = New Point(3, 15)
LabelProgramName.Name = "LabelProgramName"
LabelProgramName.Size = New Size(48, 20)
LabelProgramName.TabIndex = 3
LabelProgramName.Text = "Name"
'
' LabelProgramDescription
'
LabelProgramDescription.AutoSize = True
LabelProgramDescription.Font = New Font("Segoe UI Semibold", 9F, FontStyle.Bold, GraphicsUnit.Point)
LabelProgramDescription.ForeColor = SystemColors.ControlText
LabelProgramDescription.Location = New Point(3, 43)
LabelProgramDescription.Name = "LabelProgramDescription"
LabelProgramDescription.Size = New Size(68, 15)
LabelProgramDescription.TabIndex = 4
LabelProgramDescription.Text = "Description"
'
' LinkLabelReadtheWiki
'
LinkLabelReadtheWiki.AutoSize = True
LinkLabelReadtheWiki.Font = New Font("Segoe UI", 9F, FontStyle.Regular, GraphicsUnit.Point)
LinkLabelReadtheWiki.Location = New Point(313, 43)
LinkLabelReadtheWiki.Name = "LinkLabelReadtheWiki"
LinkLabelReadtheWiki.Size = New Size(79, 15)
LinkLabelReadtheWiki.TabIndex = 6
LinkLabelReadtheWiki.TabStop = True
LinkLabelReadtheWiki.Text = "Read the Wiki"
'
' Panel1
'
Panel1.BackColor = SystemColors.Control
Panel1.Controls.Add(LinkLabelVersion)
Panel1.Controls.Add(LabelProgramDescription)
Panel1.Controls.Add(LabelProgramName)
Panel1.Controls.Add(LinkLabelReadtheWiki)
Panel1.Location = New Point(106, 12)
Panel1.Name = "Panel1"
Panel1.Size = New Size(409, 93)
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.Font = New Font("Cambria", 9.75F, FontStyle.Regular, GraphicsUnit.Point)
LicenseRichTextBox.Location = New Point(12, 113)
LicenseRichTextBox.Name = "LicenseRichTextBox"
LicenseRichTextBox.ReadOnly = True
LicenseRichTextBox.Size = New Size(503, 329)
LicenseRichTextBox.TabIndex = 1
LicenseRichTextBox.Text = "License notice"
'
' AboutBox
'
AutoScaleDimensions = New SizeF(7F, 15F)
AutoScaleMode = AutoScaleMode.Font
BackColor = Color.Gainsboro
ClientSize = New Size(526, 453)
Controls.Add(LicenseRichTextBox)
Controls.Add(Panel1)
Controls.Add(PictureBoxLogo)
FormBorderStyle = FormBorderStyle.FixedSingle
Icon = CType(resources.GetObject("$this.Icon"), Icon)
MaximizeBox = False
MinimizeBox = False
Name = "AboutBox"
ShowInTaskbar = False
StartPosition = FormStartPosition.CenterScreen
Text = "About"
CType(PictureBoxLogo, ComponentModel.ISupportInitialize).EndInit()
Panel1.ResumeLayout(False)
Panel1.PerformLayout()
ResumeLayout(False)
End Sub
Friend WithEvents PictureBoxLogo As PictureBox
Friend WithEvents LabelProgramName As Label
Friend WithEvents LabelProgramDescription As Label
Friend WithEvents LinkLabelReadtheWiki As LinkLabel
Friend WithEvents Panel1 As Panel
Friend WithEvents LicenseRichTextBox As RichTextBox
Friend WithEvents LinkLabelVersion As LinkLabel
End Class

View File

@@ -1,758 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, 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="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="PictureBoxLogo.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAN
0AAADdABEGw9BwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAFPuSURBVHhe7d0J
nBxVvTZ+ExbZVPTPX0Svonjd5b0qV0UEARXR60Xvq2yyi4DsskR2QfZNEEE2gbAIAgEEAgQIS4BAQEh6
uqfXmUkySaYHbyCsCXuSep9fJyOdzjMz3dW1nKp++Hy+H+AH6e4659T5nao6dc57PM8TERGRDkODIiIi
km40KCIiIulGgyIiIpJuNCgiIiLpRoMiIiKSbjQoIiIi6UaDIiIikm40KCIiIulGgyIiIpJuNCgiIiLp
RoMiIiKSbjQoIiIi6UaDIiIikm40KCIiIulGgyIiIpJuNCgiIiLpRoMiIiKSbjQoIiIi6UaDIiIikm40
KCIiIulGgyIiIpJuNCgiIiLpRoMiIiKSbjQoIiIi6UaDIiIikm40KCIiIulGgyIiIpJuNCgiIiLpRoMi
IiKtGhwcXA0+Bz+B38Jf4Ba4Dx6HHMyG5+B/oQ+64DG4B26GP8Mh8APYEMaw75L20aCIiMhILDHDf8Dh
cDv0wDvgBex1sIHD9fAr+BT7PdI6GhQREWmE5LsR7A8T4HlgCTsK/XAV7AofZr9VRkeDIiIiBgl2PTgI
ngKWjOO2GCbBzrAmOwbhaFBERDoXEul7YXu4E94Glnhd9AqMh61AcwdGQYMiItJ5kDTXhiPgWWAJNkls
3oDdFRjLjlU0ABAR6XhIkuvC72ABsGSaZL2wN6zGjr2T0aCIiKQfkqJd8Z8GduucJc80mQf7gu4ILEeD
IiKSbkiEP1ueFFmyTLOnYRNWJp2GBkVEJJ2Q/D4N9y5Php1qCVwM67Iy6hQ0KCIi6YJkt8rMmTMvx9/f
AJYUO9F82JmVVyegQRERSQ8k/s/n8/nn+/v7WRKUwcEroOPWEKBBERFJh56enoO7uroWFwoFlvjkXd3w
eVaGaUWDIiKSbEhmq5RKpftnzJjhmXnz5rGkJytaCLux8kwjGhQRkeTCVf9H8vn8/OnTp3umUqmwZCfD
Ox9Sv5IgDYqISDL19vZ+JpfLLRpK/plMxqtWqyzJychugFQvHkSDIiKSPH19fZtks9k3h5K/QYwlN2nO
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
WNsXiQMNisQNg4GvlkqlK3GlNCuTySxmnaqIq2YsW463H2340r6+vs+zNi4SNxoUcU25XP4hrp5uRKc6
gAGBXi8U53R1db2K9vlQoVDYA/+uXffEeTQo4rJKpTIWA4KdMCC4Ex3uc1pvQOKAhP8a2t9TcCza4EdZ
WxVxGQ2KJAkGBGtgQPBrXHk9aJMJ9ZqhhCGTybyBZD8jn8+fguSv9/Ml8WhQJMkwIFjXlibGgOCJbDa7
kHXmIqOxV/SQ8JHv8+eiHX2OtTWRJKNBkTTBgOBjpVLpVAwIZtgbBnpkII2sTaBtvIw2Mr1YLJ6NpL8x
a0siaUKDImlXLpe3wKDgdHT4D+Eqr9rV1fU2SwySPpbscUW/AEn+SST7P6IdfA9xvY8vHYcGRToRBgXr
wz5ICtcjORSQJF7V3YJkQ/0tweDuOVzdP4qB3umo028hrhn6IkCDIrIMksUYDAq2xFXiWYVCYQqSyCAS
yjv1SUbiZ2tF2FU96mc6Bm/j8fe9Ed8IdGUvMgwaFJGRYUDwUdjf1iZAwiniCvN5DAze1B2DcKGMbWLe
cxiMdaHsr0Md2NsfG7I6EpGR0aCI+IfE9GEkpm3hSPzz5UhQ92OQkEfi+ieuUl/D1eoSltw6HQZPi5Hg
X8Fgag7K6h8oslvgTNgd5bYx/p81WHmLiD80KCLhwuBgrXK5/C3YH/98PgYKd2CgMB2Jb569qZCWxwxI
6rXb8zie15DEn8exzQRbPGcCEvsZ+Puu+O9fxv/7PlZOIhIeGhSR+NmKh/B52BwDhe1gNzgQjsag4TS4
EK7C4OEmmIgBxIMwDTJIrkWYiQQ7APORdF+EV5GEX7fb6LDY7kTAUkvQ8A5ib4L994X4/16GBfC/UMWf
7YdeKEAGnsTnPgC34nuuwHeeg99gv+tX9lt7enq+MXv27H8bHBwcw45NROJHgyIiIpJuNCgiIiLpRoMi
IiKSbjQoIiIi6UaDIiIikm40KCIiIulGgyIiIpJuNCgiIiLpRoMiIiKSbjQoIiIi6UaDIiIikm40KCIi
IulGgyIiIpJuNCgiIiLpRoMiIiKSbjQoIiIi6UaDIiIikm40KCIiIulGgyIiIpJuNCgiIiLpRoMiIiKS
bjQoIiIi6UaDIiIikm40KCIiIulGgyIiIpJuNCgiIiLpRoMiIiKSbjQoIiIi6UaDIiIikmbee/4fFi8j
zX+PctYAAAAASUVORK5CYII=
</value>
</data>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
</value>
</data>
</root>

View File

@@ -1,57 +0,0 @@
Imports System.Runtime
Public Class AboutBox
ReadOnly settings As New SettingsManager()
Public Property LicenseText As String = $"MIT License
{My.Application.Info.Copyright}
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the ""Software""), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
''' <summary>
''' Handles the Load event for the AboutBox form.
''' </summary>
''' <param name="sender">The source of the event.</param>
''' <param name="e">The event data.</param>
Private Sub AboutBox_Load(sender As Object, e As EventArgs) Handles MyBase.Load
settings.LoadSettings()
settings.ToggleSettings(settings.DarkMode, "darkmode")
LabelProgramName.Text = My.Application.Info.ProductName
LabelProgramDescription.Text = "Given a subreddit name and a keyword,
RPST returns all top posts (by default)
that contain the specified keyword."
LinkLabelVersion.Text = $"v{My.Application.Info.Version}"
LicenseRichTextBox.Text = LicenseText
End Sub
''' <summary>
''' Handles the LinkClicked event for the LinkLabelReadtheWiki control.
''' Opens the Wiki URL in the default browser.
''' </summary>
''' <param name="sender">The source of the event.</param>
''' <param name="e">The event data.</param>
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")
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

View File

@@ -1,50 +0,0 @@
Imports System.IO
Imports System.Net.Http
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
''' <summary>
''' Handles requests to Reddit and Github APIs.
''' </summary>
Public Class ApiHandler
Public Property LogFile As String = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RedditPostScrapingTool", "logs", $"debug.log")
Public Property Headers As String = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1.2 Safari/605.1.15"
Public Property UpdatesEndpoint As String = "https://api.github.com/repos/bellingcat/reddit-post-scraping-tool/releases/latest"
''' <summary>
''' Scrape Reddit data.
''' </summary>
''' <returns>Json object containing scraped data.</returns>
Public Function ScrapeReddit(subreddit As String, listing As String, limit As Integer, timeframe As String) As JObject
Dim ApiEndpoint As String = $"https://reddit.com/r/{subreddit}/{listing}.json?limit={limit}&t={timeframe}"
Return GetJObjectFromEndpoint(ApiEndpoint)
End Function
''' <summary>
''' Gets remote version information from the repository release page.
''' </summary>
''' <returns>Json object containing update data.</returns>
Public Function CheckUpdates() As JObject
Return GetJObjectFromEndpoint(UpdatesEndpoint)
End Function
Private Function GetJObjectFromEndpoint(endpoint As String) As JObject
Try
Using httpClient As New HttpClient()
httpClient.DefaultRequestHeaders.Add("User-Agent", headers)
Dim response As HttpResponseMessage = httpClient.GetAsync(endpoint).Result
If response.IsSuccessStatusCode Then
Dim json As String = response.Content.ReadAsStringAsync().Result
Dim data As JObject = JsonConvert.DeserializeObject(Of JObject)(json)
Return data
Else
MessageBox.Show(response.ReasonPhrase, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End If
End Using
Catch ex As Exception
My.Computer.FileSystem.WriteAllText(LogFile, $"{DateTime.Now}: {ex}{Environment.NewLine}", True)
MessageBox.Show($"{ex.Message}. Please see the debug log '{LogFile}' for more information.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
Return New JObject()
End Function
End Class

View File

@@ -0,0 +1,84 @@
Imports System.IO
Imports System.Net.Http
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
''' <summary>
''' Handles requests to Reddit and Github APIs.
''' </summary>
Public Class ApiHandler
Public Property LogFile As String = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RedditPostScrapingTool", "logs", $"debug.log")
Public Property Headers As String = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1.2 Safari/605.1.15"
Public Property UpdatesEndpoint As String = "https://api.github.com/repos/bellingcat/reddit-post-scraping-tool/releases/latest"
''' <summary>
''' Asyncrosnously scrape Reddit data.
''' </summary>
''' <returns>Json object containing scraped data.</returns>
Public Async Function AsyncGetPosts(subreddit As String, listing As String, limit As Integer, timeframe As String) As Task(Of JArray)
Dim PostsEndpoint As String = $"https://www.reddit.com/r/{subreddit}/{listing}.json?limit={limit}&t={timeframe}"
Return Await PaginatedPosts(endpoint:=PostsEndpoint, limit:=limit)
End Function
''' <summary>
''' Retrieves posts in a paginated manner until the specified limit is reached.
''' </summary>
''' <param name="endpoint">The API endpoint for retrieving posts.</param>
''' <param name="limit">The limit on the number of posts to retrieve.</param>
''' <returns>A Task(Of JArray) representing the asynchronous operation, which upon completion returns a JArray of posts.</returns>
Private Async Function PaginatedPosts(endpoint As String, limit As Integer) As Task(Of JArray)
Dim allPosts As New JArray()
Dim lastPostId As String = ""
Dim useAfter As Boolean = limit > 100
While allPosts.Count < limit
Dim endpointWithAfter As String = If(useAfter And Not String.IsNullOrEmpty(lastPostId), $"{endpoint}&after={lastPostId}", endpoint)
Dim postsData As JObject = Await AsyncGetData(endpoint:=endpointWithAfter)
Dim postsChildren As JArray = postsData("data")("children")
If postsChildren.Count = 0 Then
Exit While
End If
allPosts.Merge(postsChildren)
lastPostId = postsChildren.Last("data")("id").ToString()
End While
Return allPosts
End Function
''' <summary>
''' Asyncrosnously gets remote version information from the repository release page.
''' </summary>
''' <returns>Json object containing update data.</returns>
Public Async Function CheckUpdatesAsync() As Task(Of JObject)
Return Await AsyncGetData(endpoint:=UpdatesEndpoint)
End Function
''' <summary>
''' Asyncronously retrieves a JObject from the specified endpoint.
''' </summary>
''' <param name="endpoint">The URL endpoint to retrieve data from.</param>
''' <returns>A JObject containing the retrieved data.</returns>
Private Async Function AsyncGetData(endpoint As String) As Task(Of JObject)
Try
Using httpClient As New HttpClient()
httpClient.DefaultRequestHeaders.Add("User-Agent", Headers)
Dim response As HttpResponseMessage = Await httpClient.GetAsync(endpoint)
If response.IsSuccessStatusCode Then
Dim json As String = response.Content.ReadAsStringAsync().Result
Dim data As JObject = JsonConvert.DeserializeObject(Of JObject)(json)
Return data
Else
MessageBox.Show(response.ReasonPhrase, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End If
End Using
Catch ex As Exception
My.Computer.FileSystem.WriteAllText(LogFile, $"{DateTime.Now}: {ex}{Environment.NewLine}", True)
MessageBox.Show($"{ex.Message}. Please see the debug log '{LogFile}' for more information.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
Return New JObject()
End Function
End Class

View File

@@ -0,0 +1,115 @@
Imports Newtonsoft.Json.Linq
Public Class PostsProcessor
Private Shared ReadOnly ApiHandler As New ApiHandler()
''' <summary>
''' Checks if the given Reddit post contains the given keyword in its text.
''' </summary>
''' <param name="post">The Reddit post to check.</param>
''' <param name="keyword">The keyword to check for.</param>
''' <returns>True if the post contains the keyword, False otherwise.</returns>
Public Shared Function PostContainsKeyword(post As JObject, keyword As String) As Boolean
Return post("data")("selftext").ToString.ToLower(Globalization.CultureInfo.InvariantCulture).Contains(keyword.ToLower(System.Globalization.CultureInfo.InvariantCulture))
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 Async Sub ProcessRedditPosts(settings)
' Collect inputs from the user.
Dim inputs = Utilities.CollectInputs()
If inputs.HasValue Then
' Fetch Reddit posts based on the inputs.
Dim processor As New PostsProcessor()
Dim posts As JArray = Await ApiHandler.AsyncGetPosts(subreddit:=inputs.Value.Subreddit, listing:=inputs.Value.Listing, limit:=inputs.Value.Limit, timeframe:=inputs.Value.Timeframe)
Dim totalPosts As Integer = 0
Dim keywordFound As Boolean = False
Dim foundPosts As Integer = 0
Dim foundPostsList As New JArray
PostsWindow.DataGridViewPosts.Rows.Clear()
PostsWindow.DataGridViewPosts.Columns.Clear()
PostsWindow.DataGridViewPosts.Columns.Add("PostCount", "Index")
PostsWindow.DataGridViewPosts.Columns.Add("PostAuthor", "Author")
PostsWindow.DataGridViewPosts.Columns.Add("PostID", "ID")
PostsWindow.DataGridViewPosts.Columns.Add("PostTitle", "Title")
PostsWindow.DataGridViewPosts.Columns.Add("PostText", "Text")
PostsWindow.DataGridViewPosts.Columns.Add("PostSubreddit", "Subreddit")
PostsWindow.DataGridViewPosts.Columns.Add("SubredditVisibility", "Subreddit Type")
PostsWindow.DataGridViewPosts.Columns.Add("PostThumbnail", "Thumbnail")
PostsWindow.DataGridViewPosts.Columns.Add("PostIsNSFW", "NSFW")
PostsWindow.DataGridViewPosts.Columns.Add("PostIsGilded", "Is Gilded")
PostsWindow.DataGridViewPosts.Columns.Add("PostUpvotes", "Upvotes")
PostsWindow.DataGridViewPosts.Columns.Add("PostUpvoteRatio", "Upvote Ratio")
PostsWindow.DataGridViewPosts.Columns.Add("PostDownvotes", "Downvotes")
PostsWindow.DataGridViewPosts.Columns.Add("PostIsCrosspostable", "↪️ Is Shareable")
PostsWindow.DataGridViewPosts.Columns.Add("PostScore", "Score")
PostsWindow.DataGridViewPosts.Columns.Add("PostCategory", "Category")
PostsWindow.DataGridViewPosts.Columns.Add("PostDomain", "Domain")
PostsWindow.DataGridViewPosts.Columns.Add("PostPermalink", "Permalink")
PostsWindow.DataGridViewPosts.Columns.Add("PostCreatedAt", "Created At")
' Iterate over each post.
For Each post In posts
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)
PostsWindow.DataGridViewPosts.Rows.Add(totalPosts,
post("data")("author"),
post("data")("id"),
post("data")("title"),
post("data")("selftext"),
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")("is_crosspostable"),
post("data")("score"),
post("data")("category"),
post("data")("domain"),
post("data")("permalink"),
post("data")("created"))
PostsWindow.Text = $"Showing {foundPosts}/{inputs.Value.Limit} {inputs.Value.Listing} posts containing the word {inputs.Value.Keyword}, from r/{inputs.Value.Subreddit}"
PostsWindow.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(posts:=foundPostsList)
End If
If settings.SaveToCsv Then
' Save posts to a CSV file if SaveToCsv is True.
Utilities.SavePostsToCSV(posts:=foundPostsList)
End If
Else
End If
End Sub
End Class

View File

@@ -0,0 +1,230 @@
Imports System.IO
Imports System.Text.Json
Imports Newtonsoft.Json.Linq
Public Class SettingsManager
''' <summary>
''' Represents the Dark Mode property.
''' Indicates whether the dark mode is enabled or disabled.
''' </summary>
Public Property DarkMode As Boolean
Public Property SaveToJson As Boolean
Public Property SaveToCsv As Boolean
Private ReadOnly settingsFilePath As String = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"RPST",
"settings.json"
)
''' <summary>
''' Loads application settings from the 'settings.json' file.
''' If the settings file doesn't exist, it creates a new file with default settings.
''' </summary>
Public Sub LoadSettings()
' Check if the settings.json file exists
' and load the configurations from it
If File.Exists(settingsFilePath) Then
Dim json As String = File.ReadAllText(settingsFilePath)
Dim options As New JsonSerializerOptions With {.PropertyNameCaseInsensitive = True}
Dim settings = JsonSerializer.Deserialize(Of SettingsManager)(json, options)
DarkMode = settings.DarkMode
SaveToJson = settings.SaveToJson
SaveToCsv = settings.SaveToCsv
MainWindow.DarkModeToolStripMenuItem.Checked = settings.DarkMode
MainWindow.ToJSONToolStripMenuItem.Checked = settings.SaveToJson
MainWindow.ToCSVToolStripMenuItem.Checked = settings.SaveToCsv
Else
' Settings file does not exist
' Create a new file with default settings 'False'
Dim defaultSettings = New SettingsManager With {.DarkMode = False, .SaveToCsv = False, .SaveToJson = False}
Dim jsonOutput = JsonSerializer.Serialize(defaultSettings)
File.WriteAllText(settingsFilePath, jsonOutput)
SaveToJson = False
SaveToCsv = False
MainWindow.ToJSONToolStripMenuItem.Checked = False
MainWindow.ToCSVToolStripMenuItem.Checked = False
If Utilities.IsSystemDarkTheme() Then
DarkMode = True
MainWindow.DarkModeToolStripMenuItem.Checked = True
Else
DarkMode = False
MainWindow.DarkModeToolStripMenuItem.Checked = False
End If
End If
End Sub
''' <summary>
''' Retrieves application settings from a JSON file.
''' </summary>
''' <returns>A Dictionary containing the names and values of all settings.
''' If the settings file doesn't exist, returns a Dictionary with default values.</returns>
Private Function GetSettings() As Dictionary(Of String, Object)
Dim settings As New Dictionary(Of String, Object)
If File.Exists(settingsFilePath) Then
' Read and parse the JSON settings file.
Dim json As String = File.ReadAllText(settingsFilePath)
Dim jObject As JObject = JObject.Parse(json)
' 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>
''' Saves the provided settings to the 'settings.json' file.
''' </summary>
''' <param name="settings">An instance of the SettingsManager containing the configurations to be saved.</param>
Private Sub SaveSettings(settings)
Dim jsonOutput = JsonSerializer.Serialize(settings)
File.WriteAllText(settingsFilePath, jsonOutput)
End Sub
''' <summary>
''' Applies the current settings to the application's interface. This includes
''' toggling SaveToJson, SaveToCsv, and applying the visual theme based on the Dark Mode setting.
''' </summary>
Public Sub ApplySettings()
' Retrieve the current settings
Dim settings As Dictionary(Of String, Object) = GetSettings()
' Apply the SaveToJson setting to the menu item checkbox
MainWindow.ToJSONToolStripMenuItem.Checked = CBool(settings("SaveToJson"))
' Apply the SaveToCsv setting to the menu item checkbox
MainWindow.ToCSVToolStripMenuItem.Checked = CBool(settings("SaveToCsv"))
' Apply the color scheme based on the Dark Mode setting
ApplyColorScheme(isDarkMode:=CBool(settings("DarkMode")))
End Sub
''' <summary>
''' Applies the color scheme based on the given Dark Mode setting.
''' Colors are defined in a mapping for easier maintenance and flexibility.
''' </summary>
''' <param name="isDarkMode">Indicates whether Dark Mode is enabled.</param>
Public Shared Sub ApplyColorScheme(ByVal isDarkMode As Boolean)
' Initialize color mapping
Dim colorMap As New Dictionary(Of String, Color)
If isDarkMode Then
' Dark Mode colors
colorMap("MainBackground") = ColorTranslator.FromHtml("#FF121212")
colorMap("TextBoxBackground") = ColorTranslator.FromHtml("#FF2E2E2E")
colorMap("Foreground") = SystemColors.Control
colorMap("MenuBackground") = ColorTranslator.FromHtml("#FF121212")
colorMap("AboutBackground") = ColorTranslator.FromHtml("#FF121212")
colorMap("AboutForeground") = SystemColors.Control
colorMap("TabPageBackground") = ColorTranslator.FromHtml("#FF2E2E2E")
colorMap("TabPageForeground") = SystemColors.Control
colorMap("ButtonForeground") = Color.Black
Else
' Light Mode colors
colorMap("MainBackground") = Color.Gainsboro
colorMap("TextBoxBackground") = SystemColors.Control
colorMap("Foreground") = ColorTranslator.FromHtml("#FF121212")
colorMap("MenuBackground") = Color.Gainsboro
colorMap("AboutBackground") = Color.Gainsboro
colorMap("AboutForeground") = SystemColors.WindowText
colorMap("TabPageBackground") = SystemColors.Control
colorMap("TabPageForeground") = SystemColors.WindowText
colorMap("ButtonForeground") = Color.Black
End If
' Applying Main Form colors
MainWindow.BackColor = colorMap("MainBackground")
MainWindow.TextBoxKeyword.BackColor = colorMap("TextBoxBackground")
MainWindow.TextBoxSubreddit.BackColor = colorMap("TextBoxBackground")
MainWindow.NumericUpDownLimit.BackColor = colorMap("TextBoxBackground")
MainWindow.ComboBoxListing.BackColor = colorMap("TextBoxBackground")
MainWindow.ComboBoxTimeframe.BackColor = colorMap("TextBoxBackground")
MainWindow.TextBoxKeyword.ForeColor = colorMap("Foreground")
MainWindow.TextBoxSubreddit.ForeColor = colorMap("Foreground")
MainWindow.NumericUpDownLimit.ForeColor = colorMap("Foreground")
MainWindow.ComboBoxListing.ForeColor = colorMap("Foreground")
MainWindow.ComboBoxTimeframe.ForeColor = colorMap("Foreground")
MainWindow.LabelKeyword.ForeColor = colorMap("Foreground")
MainWindow.LabelSubreddit.ForeColor = colorMap("Foreground")
MainWindow.LabelLimit.ForeColor = colorMap("Foreground")
MainWindow.LabelListing.ForeColor = colorMap("Foreground")
MainWindow.LabelTimeframe.ForeColor = colorMap("Foreground")
' Applying Right-Click Menu colors
MainWindow.SettingsToolStripMenuItem.BackColor = colorMap("MenuBackground")
MainWindow.DarkModeToolStripMenuItem.BackColor = colorMap("MenuBackground")
MainWindow.SavePostsToolStripMenuItem.BackColor = colorMap("MenuBackground")
MainWindow.ToJSONToolStripMenuItem.BackColor = colorMap("MenuBackground")
MainWindow.ToCSVToolStripMenuItem.BackColor = colorMap("MenuBackground")
MainWindow.AboutToolStripMenuItem.BackColor = colorMap("MenuBackground")
MainWindow.CheckForUpdatesToolStripMenuItem.BackColor = colorMap("MenuBackground")
MainWindow.QuitToolStripMenuItem.BackColor = colorMap("MenuBackground")
MainWindow.SettingsToolStripMenuItem.ForeColor = colorMap("Foreground")
MainWindow.DarkModeToolStripMenuItem.ForeColor = colorMap("Foreground")
MainWindow.SavePostsToolStripMenuItem.ForeColor = colorMap("Foreground")
MainWindow.ToJSONToolStripMenuItem.ForeColor = colorMap("Foreground")
MainWindow.ToCSVToolStripMenuItem.ForeColor = colorMap("Foreground")
MainWindow.AboutToolStripMenuItem.ForeColor = colorMap("Foreground")
MainWindow.CheckForUpdatesToolStripMenuItem.ForeColor = colorMap("Foreground")
MainWindow.QuitToolStripMenuItem.ForeColor = colorMap("Foreground")
' Applying About Box colors
AboutBox.BackColor = colorMap("AboutBackground")
AboutBox.TabPageAbout.BackColor = colorMap("TabPageBackground")
AboutBox.TabPageAuthor.BackColor = colorMap("TabPageBackground")
AboutBox.ForeColor = colorMap("AboutForeground")
AboutBox.LabelProgramName.ForeColor = colorMap("AboutForeground")
AboutBox.LabelDescription.ForeColor = colorMap("AboutForeground")
AboutBox.LabelCopyright.ForeColor = colorMap("AboutForeground")
AboutBox.LabelVersion.ForeColor = colorMap("AboutForeground")
AboutBox.LabelAuthor.ForeColor = colorMap("AboutForeground")
AboutBox.ButtonClose.ForeColor = colorMap("ButtonForeground")
' Updating Dark Mode Text
If isDarkMode Then
MainWindow.DarkModeToolStripMenuItem.Text = "Dark Mode: Disable"
Else
MainWindow.DarkModeToolStripMenuItem.Text = "Dark Mode: Enable"
End If
End Sub
''' <summary>
''' Toggles specific settings on or off based on the provided parameters.
''' </summary>
''' <param name="enabled">A Boolean indicating if the setting option should be enabled or not.</param>
''' <param name="saveTo">A String specifying the type of setting to toggle ('json', 'csv', or 'darkmode').</param>
Public Sub ToggleSettings(enabled As Boolean, saveTo As String)
' Read the existing settings from the settings file
Dim json As String = File.ReadAllText(settingsFilePath)
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
' Handle unexpected value of saveTo (if needed)
End If
' Save the updated settings back to the settings file
SaveSettings(settings)
' Apply the updated settings to the application
ApplySettings()
End Sub
End Class

View File

@@ -1,9 +1,57 @@
Imports System.IO
Imports Microsoft.Win32
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
Public Class Utilities
''' <summary>
''' Determines if the Windows system theme is in dark mode.
''' </summary>
''' <returns>
''' True if the dark mode is enabled, otherwise false.
''' </returns>
Public Shared Function IsSystemDarkTheme() As Boolean
Dim registryKey As RegistryKey = Registry.CurrentUser.OpenSubKey(
"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"
)
If registryKey IsNot Nothing Then
Dim appsUseLightTheme As Object = registryKey.GetValue("AppsUseLightTheme")
Return appsUseLightTheme IsNot Nothing AndAlso CType(appsUseLightTheme, Integer) = 0
Else
Return False
End If
End Function
''' <summary>
''' Shows the license notice in a messagebox.
''' </summary>
''' <returns>
''' Result of the Dialog (Yes/No).
''' </returns>
Public Shared Function LicenseAgreement()
Dim result As DialogResult = MessageBox.Show($"{My.Application.Info.Copyright}
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the ""Software""), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", "MIT License", MessageBoxButtons.OK, MessageBoxIcon.Information)
Return result
End Function
''' <summary>
''' Checks for the existence of the 'logs' directory under the 'RPST' directory within the user's AppData\Roaming folder.
''' If the directory does not exist, it creates one.
@@ -14,7 +62,10 @@ Public Class Utilities
''' If the directories already exist, the function will not perform any actions.
''' </remarks>
Public Shared Sub PathFinder()
Dim directoryPath As String = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RPST", "logs")
Dim directoryPath As String = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"RPST", "logs"
)
If Not Directory.Exists(directoryPath) Then
Directory.CreateDirectory(directoryPath)
@@ -27,8 +78,8 @@ Public Class Utilities
''' </summary>
''' <returns>
''' Tuple containing:
''' Keyword (String) - Keyword entered by user in theFormMain.
''' Subreddit (String) - Subreddit entered by user in theFormMain.
''' Keyword (String) - Keyword entered by user in theMainWindow.
''' Subreddit (String) - Subreddit entered by user in theMainWindow.
''' Listing (String) - Listing chosen by user in the StartForm, defaults to 'top' if none is selected.
''' Limit (Integer) - Limit entered by user in the StartForm, defaults to 10 if the entered value is over 100.
''' Timeframe (String) - Timeframe chosen by user in the StartForm, defaults to 'all' if none is selected.
@@ -37,26 +88,22 @@ Public Class Utilities
''' If keyword or subreddit are empty, Displays a warning and returns nothing.
''' </remarks>
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 subreddit As String = FormMain.TextBoxSubreddit.Text.Trim()
''' <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 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 keyword As String = MainWindow.TextBoxKeyword.Text.Trim()
Dim subreddit As String = MainWindow.TextBoxSubreddit.Text.Trim()
' Convert the Listing and Subreddit to lowercase using InvariantCulture.
Dim listing As String = If(String.IsNullOrEmpty(MainWindow.ComboBoxListing.Text), "top", MainWindow.ComboBoxListing.Text.ToLower(Globalization.CultureInfo.InvariantCulture).Trim())
Dim timeframe As String = If(String.IsNullOrEmpty(MainWindow.ComboBoxTimeframe.Text), "all", MainWindow.ComboBoxTimeframe.Text.ToLower(Globalization.CultureInfo.InvariantCulture).Trim())
Dim limit As Integer = MainWindow.NumericUpDownLimit.Value
''' <summary>
''' Validate inputs.
''' <summary>
' Validate inputs.
If String.IsNullOrEmpty(keyword) AndAlso String.IsNullOrEmpty(subreddit) Then
MessageBox.Show("Keyword and Subreddit should not be empty.", "Invalid Inputs", MessageBoxButtons.OK, MessageBoxIcon.Warning)
MessageBox.Show("Keyword and Subreddit should not be empty.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Return Nothing
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.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Return Nothing
ElseIf String.IsNullOrEmpty(subreddit) Then
MessageBox.Show("Subreddit field should not be empty.", "Invalid Input", MessageBoxButtons.OK, MessageBoxIcon.Warning)
MessageBox.Show("Subreddit field should not be empty.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Return Nothing
End If
Return (keyword, subreddit, listing, limit, timeframe)
@@ -73,7 +120,7 @@ Public Class Utilities
''' to JSON with an indented format and written to the chosen file.
''' A success message will be displayed to the user upon successful save.
''' </remarks>
Public Shared Sub SavePostsToJson(Posts As Object)
Public Shared Sub SavePostsToJson(posts As Object)
Dim saveFileDialog As New SaveFileDialog With {
.Filter = "JSON files (*.json)|*.json",
.Title = "Save posts to JSON"
@@ -84,11 +131,11 @@ Public Class Utilities
Dim serializerSettings As New JsonSerializerSettings With {
.Formatting = Formatting.Indented
}
Dim json As String = JsonConvert.SerializeObject(Posts, serializerSettings)
Dim json As String = JsonConvert.SerializeObject(posts, serializerSettings)
File.WriteAllText(fileName, json)
MessageBox.Show($"Posts saved to {fileName}", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information)
MessageBox.Show($"Posts saved to {fileName}", "Saved", MessageBoxButtons.OK, MessageBoxIcon.Information)
End If
End Sub
@@ -110,9 +157,7 @@ Public Class Utilities
If saveFileDialog.ShowDialog() = DialogResult.OK Then
Dim fileName As String = saveFileDialog.FileName
Using csvWriter As New StreamWriter(fileName)
''' <summary>
''' Write the header.
''' <summary>
' Write the header.
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
@@ -122,46 +167,7 @@ Public Class Utilities
Next
End Using
MessageBox.Show($"Posts saved to {fileName}", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information)
End If
End Sub
''' <summary>
''' Shows the license notice in a messagebox.
''' </summary>
''' <remarks>
''' The license text is retrieved from the AboutBox.LicenseText property.
''' The messagebox is displayed with the title "License" and an information icon.
''' </remarks>
Public Shared Sub LicenseNotice()
MessageBox.Show(AboutBox.LicenseText, "License", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
''' <summary>
''' Checks if the "first-launch.log" file exists in the directory: C:\Users\<username>\AppData\Roaming\RedditPostScrapingTool\logs.
''' If the file doesn't exist, it creates one. This file is used to determine whether the program has been run before.
''' If the program is being run for the first time, a license notice will be displayed.
''' </summary>
Public Shared Sub LogFirstTimeLaunch()
Dim filePath As String = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RPST", "logs", "first-launch.log")
Dim textToWrite As String = $"
{My.Application.Info.AssemblyName}
-------------------------
User: {Environment.UserName}
Host: {Environment.MachineName}
OS: {Environment.OSVersion}
x64: {Environment.Is64BitOperatingSystem}
First launched on: {DateTime.Now}"
If Not File.Exists(filePath) Then
LicenseNotice()
File.WriteAllText(filePath, textToWrite)
Else
MessageBox.Show($"Posts saved to {fileName}", "Saved", MessageBoxButtons.OK, MessageBoxIcon.Information)
End If
End Sub
End Class

View File

@@ -1,69 +0,0 @@
Imports Newtonsoft.Json.Linq
Public Class DataGridViewHandler
''' <summary>
''' Initializes the DataGridView by clearing any existing data and setting up the necessary columns.
''' </summary>
''' <param name="dataGridView">The DataGridView to be initialized.</param>
Public Shared Sub AddColumn(dataGridView As DataGridView)
''' <summary>
''' Clear the Columns and Rows before adding Items to them.
''' <summary>
dataGridView.Rows.Clear()
dataGridView.Columns.Clear()
dataGridView.Columns.Add("PostCount", "🔢 Index")
dataGridView.Columns.Add("PostAuthor", "👤 Author")
dataGridView.Columns.Add("PostID", "🆔 ID")
dataGridView.Columns.Add("PostText", "📝 Text")
dataGridView.Columns.Add("PostSubreddit", "🫂 Subreddit")
dataGridView.Columns.Add("SubredditVisibility", "🫣 Visibility")
dataGridView.Columns.Add("PostThumbnail", "🖼️ Thumbnail")
dataGridView.Columns.Add("PostIsNSFW", "🔞 NSFW")
dataGridView.Columns.Add("PostIsGilded", "🥇 Gilded")
dataGridView.Columns.Add("PostUpvotes", "⬆️ Upvotes")
dataGridView.Columns.Add("PostUpvoteRatio", "📊 Upvote Ratio")
dataGridView.Columns.Add("PostDownvotes", "⬇️ Downvotes")
dataGridView.Columns.Add("PostAwards", "🏆 Awards")
dataGridView.Columns.Add("PostTopAward", "🏆 Top Award")
dataGridView.Columns.Add("PostIsCrosspostable", "↪️ Is cross-postable?")
dataGridView.Columns.Add("PostScore", "📈 Score")
dataGridView.Columns.Add("PostCategory", "🟢 Category")
dataGridView.Columns.Add("PostDomain", "🌐 Domain")
dataGridView.Columns.Add("PostPermalink", "🔗 Permalink")
dataGridView.Columns.Add("PostCreatedAt", "📅 Created At")
dataGridView.Columns.Add("PostApprovedAt", "📅 Approved At")
dataGridView.Columns.Add("PostApprovedBy", "👤 Approved By")
End Sub
Public Shared Sub AddRow(dataGridView As DataGridView, post As JObject, postNumber As Integer)
''' <summary>
''' Adds a row to the DataGridView based on the data from a Reddit post.
''' </summary>
''' <param name="dataGridView">The DataGridView to which the row will be added.</param>
''' <param name="post">A JObject representing the Reddit post.</param>
''' <param name="postNumber">The number of the post.</param>
dataGridView.Rows.Add(postNumber,
post("data")("author"),
post("data")("id"),
post("data")("selftext"),
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")("domain"),
post("data")("permalink"),
post("data")("created"),
post("data")("approved_at_utc"),
post("data")("approved_by"))
End Sub
End Class

View File

@@ -1,89 +0,0 @@
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Class DeveloperBox
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()>
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Dim resources As ComponentModel.ComponentResourceManager = New ComponentModel.ComponentResourceManager(GetType(DeveloperBox))
AboutMeLinkLabel = New LinkLabel()
LinkLabelBuyMeACoffee = New LinkLabel()
GreetingLabel = New Label()
SuspendLayout()
'
' AboutMeLinkLabel
'
AboutMeLinkLabel.AutoSize = True
AboutMeLinkLabel.BackColor = Color.White
AboutMeLinkLabel.Font = New Font("Comic Sans MS", 9F, FontStyle.Regular, GraphicsUnit.Point)
AboutMeLinkLabel.Location = New Point(33, 426)
AboutMeLinkLabel.Name = "AboutMeLinkLabel"
AboutMeLinkLabel.Size = New Size(57, 17)
AboutMeLinkLabel.TabIndex = 0
AboutMeLinkLabel.TabStop = True
AboutMeLinkLabel.Text = "About.me"
'
' LinkLabelBuyMeACoffee
'
LinkLabelBuyMeACoffee.AutoSize = True
LinkLabelBuyMeACoffee.Font = New Font("Comic Sans MS", 9F, FontStyle.Regular, GraphicsUnit.Point)
LinkLabelBuyMeACoffee.Location = New Point(33, 451)
LinkLabelBuyMeACoffee.Name = "LinkLabelBuyMeACoffee"
LinkLabelBuyMeACoffee.Size = New Size(101, 17)
LinkLabelBuyMeACoffee.TabIndex = 1
LinkLabelBuyMeACoffee.TabStop = True
LinkLabelBuyMeACoffee.Text = "Buy Me A Coffee"
'
' GreetingLabel
'
GreetingLabel.AutoSize = True
GreetingLabel.Font = New Font("Ink Free", 27.75F, FontStyle.Bold, GraphicsUnit.Point)
GreetingLabel.Location = New Point(62, 22)
GreetingLabel.Name = "GreetingLabel"
GreetingLabel.Size = New Size(355, 46)
GreetingLabel.TabIndex = 3
GreetingLabel.Text = "👋🏾Hello, I'm Ritchie"
'
' DeveloperBox
'
AutoScaleDimensions = New SizeF(7F, 15F)
AutoScaleMode = AutoScaleMode.Font
BackgroundImage = CType(resources.GetObject("$this.BackgroundImage"), Image)
ClientSize = New Size(510, 510)
Controls.Add(LinkLabelBuyMeACoffee)
Controls.Add(AboutMeLinkLabel)
Controls.Add(GreetingLabel)
FormBorderStyle = FormBorderStyle.FixedSingle
MaximizeBox = False
MinimizeBox = False
Name = "DeveloperBox"
ShowIcon = False
ShowInTaskbar = False
StartPosition = FormStartPosition.CenterParent
Text = "Developer"
ResumeLayout(False)
PerformLayout()
End Sub
Friend WithEvents AboutMeLinkLabel As LinkLabel
Friend WithEvents LinkLabelBuyMeACoffee As LinkLabel
Friend WithEvents PictureBox1 As PictureBox
Friend WithEvents GreetingLabel As Label
End Class

View File

@@ -1,874 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, 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="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
/9j/4AAQSkZJRgABAQEAAAAAAAD/4gIoSUNDX1BST0ZJTEUAAQEAAAIYAAAAAAQwAABtbnRyUkdCIFhZ
WiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAA
AHRyWFlaAAABZAAAABRnWFlaAAABeAAAABRiWFlaAAABjAAAABRyVFJDAAABoAAAAChnVFJDAAABoAAA
AChiVFJDAAABoAAAACh3dHB0AAAByAAAABRjcHJ0AAAB3AAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAA
AFgAAAAcAHMAUgBHAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAA
AAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z3BhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAA
E9AAAApbAAAAAAAAAABYWVogAAAAAAAA9tYAAQAAAADTLW1sdWMAAAAAAAAAAQAAAAxlblVTAAAAIAAA
ABwARwBvAG8AZwBsAGUAIABJAG4AYwAuACAAMgAwADEANv/bAEMAAQEBAQEBAQEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/bAEMBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAgAC
AAMBIgACEQEDEQH/xAAfAAEAAQUBAQEBAQAAAAAAAAAABgQFBwgJCgMCCwH/xABHEAABAwMDAgQDBAcG
BQMDBQABAgMEAAURBhIhBzEIE0FRFCJhCTJxgRUjQpGhscEWUmLR4fAkM3KCwgoXNCU3kkOyx9Lx/8QA
HQEBAAIDAQEBAQAAAAAAAAAAAAUGAwQHAggBCf/EAEIRAAEDAwMCAwUFBwMCBQUAAAEAAhEDBCEFEjFB
UQYTYQciMnGBFJGhsfAVI0JiwdHxM1LhFoIkQ3KSwghTc6Li/9oADAMBAAIRAxEAPwD1YUpSrQqulKUo
iUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKI
lKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJ
SlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiU
pSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlK
UoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSl
KIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpS
iJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUo
iUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKI
lKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJ
SlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiU
pSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlK
UoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSl
KIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpS
iJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUo
iUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKI
lKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJ
SlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiU
pSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlR7VGrNNaKs8m/6svlt0/Z4qVl2dc5TcZtbiGHpHw0ZKz5s
ya6zHeVGgQ235spTam4zDrmEn8JDQXOIAAkkkAADkknAA7le6dN9V7KdJj6lSo4MZTptL3ve4w1rGNBc
5zjgNAJJwApDSuXHWD7SPT1ofmWXpNYf00psuxzq/UJdhwkutuuIW7atPJb+MlMuRlMSYM+7SbeW3y5H
mWJ7yHmzovrjx6dcr+35TWurnbkKTJSqPYWYGnw38RI80BqbZYcC6BDLLcdhhTs9+S2EPuJlf8W8iq1e
+LtGsnFhruruGP3ADmTMRvc5rTyMs3gzicx0HRvZd4t1gU3i0o2FOrJYdQqmjUc0RJ8hjKlVp/kqNpux
kAQT6KnnmYzL0iQ81Hjx2nHn33nENMsstILjrzzrhShtptCVLccWpKEISVKIAJrHMvrR0dgSXYc7qx00
hS2Fqbfiy9d6WjSWVoWttaHWHrqh1taHG1tqStIKVoWggKSQPLhq3rTrDVEhcrUepdQ32a/HYbfn36+3
O9zng2lKQFSblKkKTGBZa8qO0EJaS03y46C6cc/22lgn9YsjPHzD6/6e9V2t7Q7cuAtbPeOrqlXPeNrG
iMZ+I/jKvlj7Crh0/tLW/JdgNZb2W4TOf3lS4EiOIpieZAC9bLfWLpE64hlrqn04cdc3BtpvXGmVuOFC
FOLCEJuhUra2lS1bQdqEqUcJBIuMXqX05muliFr/AETLfS2p5TMXVVikOpaQpCFultqetYbQt1tClkbU
qcQkkFaQfIk7raQ5glxQ2gn7yT6H3J/pVE7raUsJTvVhORncnnn8CMfhXke0BzS0P0wEntcFvbgmm4cz
/nByV/YdRpgGn4iqmRw7TWug/S8bjpAHSZhexOFqnTNxktwrfqKxT5j2/wAmJCu9vlSXfLbW655bDEhx
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
iJSlKIlKUoiUpSiJSlKIlKUoiUpSiL//2Q==
</value>
</data>
</root>

View File

@@ -1,17 +0,0 @@
Public Class DeveloperBox
Private Sub DeveloperForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
GreetingLabel.BackColor = Color.Transparent
AboutMeLinkLabel.BackColor = Color.Transparent
LinkLabelBuyMeACoffee.BackColor = Color.Transparent
End Sub
Private Sub AboutMeLinkLabel_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) Handles AboutMeLinkLabel.LinkClicked
' I couldn't find a proper way to open a url
' Process.Start() did not work
Shell("cmd /c start https://about.me/rly0nheart")
End Sub
Private Sub BuyMeACoffeeLinkLabel_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) Handles LinkLabelBuyMeACoffee.LinkClicked
Shell("cmd /c start https://buymeacoffee.com/_rly0nheart")
End Sub
End Class

View File

@@ -1,59 +0,0 @@
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Class FormPosts
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()>
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Dim resources As ComponentModel.ComponentResourceManager = New ComponentModel.ComponentResourceManager(GetType(FormPosts))
DataGridViewPosts = New DataGridView()
CType(DataGridViewPosts, ComponentModel.ISupportInitialize).BeginInit()
SuspendLayout()
'
' DataGridViewPosts
'
DataGridViewPosts.BackgroundColor = Color.Gainsboro
DataGridViewPosts.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize
DataGridViewPosts.Dock = DockStyle.Fill
DataGridViewPosts.Location = New Point(0, 0)
DataGridViewPosts.Name = "DataGridViewPosts"
DataGridViewPosts.ReadOnly = True
DataGridViewPosts.RowHeadersVisible = False
DataGridViewPosts.RowTemplate.Height = 25
DataGridViewPosts.Size = New Size(501, 365)
DataGridViewPosts.TabIndex = 3
'
' FormPosts
'
AutoScaleDimensions = New SizeF(7F, 15F)
AutoScaleMode = AutoScaleMode.Font
ClientSize = New Size(501, 365)
Controls.Add(DataGridViewPosts)
Icon = CType(resources.GetObject("$this.Icon"), Icon)
Name = "FormPosts"
ShowInTaskbar = False
StartPosition = FormStartPosition.CenterScreen
Text = "Posts"
CType(DataGridViewPosts, ComponentModel.ISupportInitialize).EndInit()
ResumeLayout(False)
End Sub
Friend WithEvents DataGridViewPosts As DataGridView
End Class

View File

@@ -1,393 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, 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="Color1" type="System.Drawing.Color, System.Drawing"">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
</value>
</data>
</root>

View File

@@ -1,5 +0,0 @@
Public Class FormPosts
Private Sub FormResults_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.Text = $"{Me.Text} - {FormMain.TextBoxKeyword.Text}, r/{FormMain.TextBoxSubreddit.Text}, {FormMain.NumericUpDownLimit.Text}, {FormMain.ComboBoxListing.Text}, {FormMain.ComboBoxTimeframe.Text}"
End Sub
End Class

19
RPST GUI/RPST/LICENSE.rtf Normal file
View File

@@ -0,0 +1,19 @@
{\rtf1\ansi\ansicpg1252\cocoartf2577
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
{\*\expandedcolortbl;;}
\paperw11900\paperh16840\margl1440\margr1440\vieww13560\viewh17700\viewkind0
\pard\tx0\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\partightenfactor0
{
{\header The MIT License (MIT)}
The MIT License (MIT)\par
\fs20\li0\fi0 Copyright (c) 2023 Richard Mwewa
\par\par
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
\par\par
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
\par\par
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\par
}
}

View File

@@ -33,7 +33,13 @@ Namespace My
<Global.System.Diagnostics.DebuggerStepThroughAttribute()> _
Protected Overrides Sub OnCreateMainForm()
Me.MainForm = Global.RPST.FormMain
Me.MainForm = Global.RPST.MainWindow
End Sub
<Global.System.Diagnostics.DebuggerStepThroughAttribute()>
Protected Overrides Function OnInitialize(ByVal commandLineArgs As System.Collections.ObjectModel.ReadOnlyCollection(Of String)) As Boolean
Me.MinimumSplashScreenDisplayTime = 2000
Return MyBase.OnInitialize(commandLineArgs)
End Function
End Class
End Namespace

View File

@@ -1,10 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-16"?>
<MyApplicationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MySubMain>true</MySubMain>
<MainForm>Form1</MainForm>
<MainForm>MainWindow</MainForm>
<SingleInstance>false</SingleInstance>
<ShutdownMode>0</ShutdownMode>
<EnableVisualStyles>true</EnableVisualStyles>
<AuthenticationMode>0</AuthenticationMode>
<SaveMySettingsOnExit>true</SaveMySettingsOnExit>
<SplashScreen></SplashScreen>
<MinimumSplashScreenDisplayTime>2000</MinimumSplashScreenDisplayTime>
</MyApplicationData>

View File

@@ -1,88 +0,0 @@
Imports Newtonsoft.Json.Linq
Public Class PostsProcessor
Private ReadOnly ApiHandler As New ApiHandler
''' <summary>
''' Fetches Reddit posts based on the given parameters and returns them as a JObject.
''' </summary>
''' <param name="subreddit">The subreddit to fetch posts from.</param>
''' <param name="listing">The type of listing (e.g., "new", "top", etc.).</param>
''' <param name="limit">The maximum number of posts to fetch.</param>
''' <param name="timeframe">The timeframe to consider for the posts (e.g., "day", "week", "month", "year", "all").</param>
''' <returns>A JObject containing the fetched Reddit posts.</returns>
Public Function FetchPosts(subreddit As String, listing As String, limit As Integer, timeframe As String) As JObject
Dim posts As JObject = ApiHandler.ScrapeReddit(subreddit, listing, limit, timeframe)
Return posts
End Function
''' <summary>
''' Checks if the given Reddit post contains the given keyword in its text.
''' </summary>
''' <param name="post">The Reddit post to check.</param>
''' <param name="keyword">The keyword to check for.</param>
''' <returns>True if the post contains the keyword, False otherwise.</returns>
Public Shared Function PostContainsKeyword(post As JObject, keyword As String) As Boolean
Return post("data")("selftext").ToString.ToLower(Globalization.CultureInfo.InvariantCulture).Contains(keyword.ToLower(System.Globalization.CultureInfo.InvariantCulture))
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

View File

@@ -1,42 +1,52 @@
![rpst](https://github.com/bellingcat/reddit-post-scraping-tool/assets/74001397/b9ec50b2-d2cb-419f-b8f0-d170b0630875)
## Note
> Use [Knew Karma](https://github.com/bellingcat/knewkarma) for more advanced and improved features.
# RPST (Reddit Post Scraping Tool)
Given a subreddit name and a keyword, RPST will return all posts from a specified listing (default is 'top') that contain the provided keyword.
Retrieve **Reddit** posts that contain the specified **keyword** from a specified **subreddit**.
[![Upload Python Package](https://github.com/bellingcat/reddit-post-scraping-tool/actions/workflows/python-publish.yml/badge.svg)](https://github.com/rly0nheart/reddit-post-scraping-tool/actions/workflows/python-publish.yml) [![CodeQL](https://github.com/bellingcat/reddit-post-scraping-tool/actions/workflows/codeql.yml/badge.svg)](https://github.com/rly0nheart/reddit-post-scraping-tool/actions/workflows/codeql.yml) ![.Net](https://img.shields.io/badge/.NET-5C2D91?style=flat&logo=.net&logoColor=white) ![Python](https://img.shields.io/badge/python-3670A0?style=flat&logo=python&logoColor=ffdd54)
# ✅ Features
## *GUI*
- [x] Dark mode (*Right-click*).
- [x] Saves results to a JSON file (*Right-click*).
- [x] Dark mode (*Right-click>Settings>Dark Mode*).
- [x] Saves results to a JSON/CSV file (*Right-click>Settings>Save posts>to JSON/to CSV*).
- [x] Logs errors to a file.
- [x] In-App feature to check for Updates.
## *CLI*
- [x] Saves results to JSON (*specifiy* `--json`).
- [x] Saves results to CSV (*specify* `--csv`).
- [x] Automatically checks for new updates, and notifies user if updates were found.
# 📃 TODO
## *GUI*
- [ ] Make it installable with a setup.exe/setup.msi file.
- [x] Add manual dark mode option, that will be persistent in all sessions.
- [x] Make settings persistent in all sessions.
- [x] Make it save results to a CSV file.
# 🖥️ Tested environments
## *GUI*
- [x] Microsoft Windows 11
## *CLI*
- [x] Android Termux
- [x] Microsoft Windows 11
- [x] Ubuntu 22.04 - latest versions
# 📖 Wiki
[Refer to the Wiki](https://github.com/bellingcat/reddit-post-scraping-tool/wiki) for installation instructions, in addition to all other documentation.
# 📖 Documentation
[Refer to the Wiki](https://github.com/bellingcat/reddit-post-scraping-tool/wiki) for installation instructions, in
addition to all other documentation.
# 🖼️ Screenshots
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>
![me](https://github.com/bellingcat/reddit-post-scraping-tool/assets/74001397/21e0bb33-7a84-45d6-92ba-00e40891ba31)
[![me](https://github.com/bellingcat/knewkarma/assets/74001397/efd19c7e-9840-4969-b33c-04087e73e4da)](https://about.me/rly0nheart)

View File

@@ -6,18 +6,18 @@
<StartupObject>RPST.My.MyApplication</StartupObject>
<UseWindowsForms>true</UseWindowsForms>
<MyType>WindowsForms</MyType>
<ApplicationIcon>icon.ico</ApplicationIcon>
<Company>Bellingcat</Company>
<Description>Given a subreddit name and a keyword, RPST (Reddit Post Scraping Tool) returns all top (by default) posts that contain the specified keyword. </Description>
<Copyright>Copyright (c) 2023 Richard Mwewa</Copyright>
<ApplicationIcon>Resources\icon.ico</ApplicationIcon>
<Company>Richard Mwewa</Company>
<Description>Retrieve Reddit posts that contain the specified keyword from a specified subreddit. </Description>
<Copyright>© 2023 Richard Mwewa. All rights reserved.</Copyright>
<PackageProjectUrl>https://github.com/bellingcat/reddit-post-scraping-tool</PackageProjectUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryUrl>https://github.com/bellingcat/reddit-post-scraping-tool</RepositoryUrl>
<AssemblyVersion>1.8.0.0</AssemblyVersion>
<FileVersion>1.8.0.0</FileVersion>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
<FileVersion>2.0.0.0</FileVersion>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
<Version>1.8.0</Version>
<Version>2.0.0</Version>
<PackageTags>reddit;scraper;reddit-scraper;osint</PackageTags>
<PackageReleaseNotes></PackageReleaseNotes>
<AnalysisLevel>6.0-recommended</AnalysisLevel>
@@ -26,10 +26,12 @@
<NeutralLanguage>en</NeutralLanguage>
<Product>$(AssemblyName) (Reddit Post Scraping Tool)</Product>
<AssemblyName>RPST</AssemblyName>
<Title>Reddit Post Scraping Tool.</Title>
<PackageIcon>icon.png</PackageIcon>
</PropertyGroup>
<ItemGroup>
<Content Include="icon.ico" />
<Content Include="Resources\icon.ico" />
</ItemGroup>
<ItemGroup>
@@ -76,6 +78,10 @@
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
<None Update="Resources\icon.png">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>
</Project>

View File

@@ -1,16 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Compile Update="AboutBox.vb">
<Compile Update="Windows\AboutBox.vb">
<SubType>Form</SubType>
</Compile>
<Compile Update="DeveloperBox.vb">
<Compile Update="Windows\MainWindow.vb">
<SubType>Form</SubType>
</Compile>
<Compile Update="FormMain.vb">
<SubType>Form</SubType>
</Compile>
<Compile Update="FormPosts.vb">
<Compile Update="Windows\PostsWindow.vb">
<SubType>Form</SubType>
</Compile>
</ItemGroup>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@@ -1,254 +0,0 @@
Imports System.IO
Imports System.Text.Json
Imports Newtonsoft.Json.Linq
Public Class SettingsManager
''' <summary>
''' Represents the Dark Mode property.
''' Indicates whether the dark mode is enabled or disabled.
''' </summary>
Public Property DarkMode As Boolean
Public Property SaveToJson As Boolean
Public Property SaveToCsv As Boolean
Private ReadOnly settingsFilePath As String = Path.Combine(Environment.CurrentDirectory, "config.json")
''' <summary>
''' Loads application settings from the 'settings.json' file.
''' If the settings file doesn't exist, it creates a new file with default settings.
''' </summary>
Public Sub LoadSettings()
' Check if the settings.json file exists
' and load the configurations from it
If File.Exists(settingsFilePath) Then
Dim json As String = File.ReadAllText(settingsFilePath)
Dim options As New JsonSerializerOptions With {.PropertyNameCaseInsensitive = True}
Dim settings = JsonSerializer.Deserialize(Of SettingsManager)(json, options)
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
' Settings file does not exist
' Create a new file with default settings 'False'
Dim defaultSettings = New SettingsManager With {.DarkMode = False, .SaveToCsv = False, .SaveToJson = False}
Dim jsonOutput = JsonSerializer.Serialize(defaultSettings)
File.WriteAllText(settingsFilePath, jsonOutput)
DarkMode = False
SaveToJson = False
SaveToCsv = False
FormMain.ToJSONToolStripMenuItem.Checked = False
FormMain.ToCSVToolStripMenuItem.Checked = False
FormMain.DarkModeToolStripMenuItem.Checked = False
End If
End Sub
''' <summary>
''' Retrieves application settings from a JSON file.
''' </summary>
''' <returns>A Dictionary containing the names and values of all settings.
''' If the settings file doesn't exist, returns a Dictionary with default values.</returns>
Private Function GetSettings() As Dictionary(Of String, Object)
Dim settings As New Dictionary(Of String, Object)
If File.Exists(settingsFilePath) Then
' Read and parse the JSON settings file.
Dim json As String = File.ReadAllText(settingsFilePath)
Dim jObject As JObject = JObject.Parse(json)
' 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>
''' Saves the provided settings to the 'settings.json' file.
''' </summary>
''' <param name="settings">An instance of the SettingsManager containing the configurations to be saved.</param>
Private Sub SaveSettings(settings)
Dim jsonOutput = JsonSerializer.Serialize(settings)
File.WriteAllText(settingsFilePath, jsonOutput)
End Sub
''' <summary>
''' Applies the current settings to the application's interface. This includes
''' toggling SaveToJson, SaveToCsv, and applying the visual theme based on the Dark Mode setting.
''' </summary>
Public Sub ApplySettings()
' Retrieve the current settings
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
' Background colours (I know 'Colours'/'Colors'😆)
FormMain.BackColor = ColorTranslator.FromHtml("#FF121212")
FormMain.TextBoxSubreddit.BackColor = ColorTranslator.FromHtml("#FF2E2E2E")
FormMain.TextBoxKeyword.BackColor = ColorTranslator.FromHtml("#FF2E2E2E")
FormMain.NumericUpDownLimit.BackColor = ColorTranslator.FromHtml("#FF2E2E2E")
FormMain.NumericUpDownLimit.BackColor = ColorTranslator.FromHtml("#FF2E2E2E")
FormMain.ComboBoxListing.BackColor = ColorTranslator.FromHtml("#FF2E2E2E")
FormMain.ComboBoxTimeframe.BackColor = ColorTranslator.FromHtml("#FF2E2E2E")
' Foreground colours
FormMain.TextBoxKeyword.ForeColor = SystemColors.Control
FormMain.TextBoxSubreddit.ForeColor = SystemColors.Control
FormMain.NumericUpDownLimit.ForeColor = SystemColors.Control
FormMain.NumericUpDownLimit.ForeColor = SystemColors.Control
FormMain.ComboBoxListing.ForeColor = SystemColors.Control
FormMain.ComboBoxTimeframe.ForeColor = SystemColors.Control
FormMain.LabelKeyword.ForeColor = SystemColors.Control
FormMain.LabelSubreddit.ForeColor = SystemColors.Control
FormMain.LabelLimit.ForeColor = SystemColors.Control
FormMain.LabelListing.ForeColor = SystemColors.Control
FormMain.LabelTimeframe.ForeColor = SystemColors.Control
' Enable dark mode on 'Right Click Menu' items
' Background colours
FormMain.SettingsToolStripMenuItem.BackColor = ColorTranslator.FromHtml("#FF121212")
FormMain.DarkModeToolStripMenuItem.BackColor = ColorTranslator.FromHtml("#FF121212")
FormMain.SavePostsToolStripMenuItem.BackColor = ColorTranslator.FromHtml("#FF121212")
FormMain.ToJSONToolStripMenuItem.BackColor = ColorTranslator.FromHtml("#FF121212")
FormMain.ToCSVToolStripMenuItem.BackColor = ColorTranslator.FromHtml("#FF121212")
FormMain.AboutToolStripMenuItem.BackColor = ColorTranslator.FromHtml("#FF121212")
FormMain.DeveloperToolStripMenuItem.BackColor = ColorTranslator.FromHtml("#FF121212")
FormMain.CheckForUpdatesToolStripMenuItem.BackColor = ColorTranslator.FromHtml("#FF121212")
FormMain.QuitToolStripMenuItem.BackColor = ColorTranslator.FromHtml("#FF121212")
' Foreground colours
FormMain.SettingsToolStripMenuItem.ForeColor = SystemColors.Control
FormMain.DarkModeToolStripMenuItem.ForeColor = SystemColors.Control
FormMain.SavePostsToolStripMenuItem.ForeColor = SystemColors.Control
FormMain.ToJSONToolStripMenuItem.ForeColor = SystemColors.Control
FormMain.ToCSVToolStripMenuItem.ForeColor = SystemColors.Control
FormMain.AboutToolStripMenuItem.ForeColor = SystemColors.Control
FormMain.DeveloperToolStripMenuItem.ForeColor = SystemColors.Control
FormMain.CheckForUpdatesToolStripMenuItem.ForeColor = SystemColors.Control
FormMain.QuitToolStripMenuItem.ForeColor = SystemColors.Control
' Enable dark mode for the About box
' Background colours
AboutBox.BackColor = ColorTranslator.FromHtml("#FF121212")
AboutBox.LicenseRichTextBox.BackColor = ColorTranslator.FromHtml("#FF2E2E2E")
AboutBox.Panel1.BackColor = ColorTranslator.FromHtml("#FF121212")
' Foreground colours
AboutBox.ForeColor = SystemColors.Control
AboutBox.LicenseRichTextBox.ForeColor = SystemColors.Control
AboutBox.LabelProgramName.ForeColor = SystemColors.Control
AboutBox.LabelProgramDescription.ForeColor = SystemColors.Control
AboutBox.LinkLabelVersion.ForeColor = SystemColors.Control
' If dark mode is enabled, set the 'Dark Mode' text value to 'Light mode'
FormMain.DarkModeToolStripMenuItem.Text = "Dark Mode: Enabled"
Else
' Disable dark mode for the Main Form
' Background colours
FormMain.BackColor = Color.Gainsboro
FormMain.TextBoxKeyword.BackColor = SystemColors.Control
FormMain.TextBoxSubreddit.BackColor = SystemColors.Control
FormMain.NumericUpDownLimit.BackColor = SystemColors.Control
FormMain.NumericUpDownLimit.BackColor = SystemColors.Control
FormMain.ComboBoxTimeframe.BackColor = SystemColors.Control
FormMain.ComboBoxListing.BackColor = SystemColors.Control
' Foreground colours
FormMain.TextBoxKeyword.ForeColor = ColorTranslator.FromHtml("#FF121212")
FormMain.TextBoxSubreddit.ForeColor = ColorTranslator.FromHtml("#FF121212")
FormMain.NumericUpDownLimit.ForeColor = ColorTranslator.FromHtml("#FF121212")
FormMain.NumericUpDownLimit.ForeColor = ColorTranslator.FromHtml("#FF121212")
FormMain.ComboBoxListing.ForeColor = ColorTranslator.FromHtml("#FF121212")
FormMain.ComboBoxTimeframe.ForeColor = ColorTranslator.FromHtml("#FF121212")
FormMain.LabelKeyword.ForeColor = ColorTranslator.FromHtml("#FF121212")
FormMain.LabelSubreddit.ForeColor = ColorTranslator.FromHtml("#FF121212")
FormMain.LabelLimit.ForeColor = ColorTranslator.FromHtml("#FF121212")
FormMain.LabelListing.ForeColor = ColorTranslator.FromHtml("#FF121212")
FormMain.LabelTimeframe.ForeColor = ColorTranslator.FromHtml("#FF121212")
' Disable dark mode on 'Right Click Menu' items
' Background colours
FormMain.SettingsToolStripMenuItem.BackColor = Color.Gainsboro
FormMain.DarkModeToolStripMenuItem.BackColor = Color.Gainsboro
FormMain.SavePostsToolStripMenuItem.BackColor = Color.Gainsboro
FormMain.ToJSONToolStripMenuItem.BackColor = Color.Gainsboro
FormMain.ToCSVToolStripMenuItem.BackColor = Color.Gainsboro
FormMain.AboutToolStripMenuItem.BackColor = Color.Gainsboro
FormMain.DeveloperToolStripMenuItem.BackColor = Color.Gainsboro
FormMain.CheckForUpdatesToolStripMenuItem.BackColor = Color.Gainsboro
FormMain.QuitToolStripMenuItem.BackColor = Color.Gainsboro
' Foreground colours
FormMain.SettingsToolStripMenuItem.ForeColor = Color.Black
FormMain.DarkModeToolStripMenuItem.ForeColor = Color.Black
FormMain.SavePostsToolStripMenuItem.ForeColor = Color.Black
FormMain.ToJSONToolStripMenuItem.ForeColor = Color.Black
FormMain.ToCSVToolStripMenuItem.ForeColor = Color.Black
FormMain.AboutToolStripMenuItem.ForeColor = Color.Black
FormMain.DeveloperToolStripMenuItem.ForeColor = Color.Black
FormMain.CheckForUpdatesToolStripMenuItem.ForeColor = Color.Black
FormMain.QuitToolStripMenuItem.ForeColor = Color.Black
' Disable dark mode for the About box
' Background colours
AboutBox.BackColor = Color.Gainsboro
AboutBox.ForeColor = SystemColors.WindowText
AboutBox.LicenseRichTextBox.BackColor = SystemColors.Control
AboutBox.LicenseRichTextBox.ForeColor = SystemColors.WindowText
AboutBox.Panel1.BackColor = Color.Gainsboro
' Foreground colours
AboutBox.Panel1.ForeColor = SystemColors.WindowText
AboutBox.LabelProgramName.ForeColor = SystemColors.WindowText
AboutBox.LabelProgramDescription.ForeColor = SystemColors.WindowText
AboutBox.LinkLabelVersion.ForeColor = SystemColors.WindowText
' If dark mode is disabled, set the 'Light Mode' text value to 'Dark Mode'
FormMain.DarkModeToolStripMenuItem.Text = "Dark Mode: Disabled"
End If
End Sub
''' <summary>
''' Toggles specific settings on or off based on the provided parameters.
''' </summary>
''' <param name="enabled">A Boolean indicating if the setting option should be enabled or not.</param>
''' <param name="saveTo">A String specifying the type of setting to toggle ('json', 'csv', or 'darkmode').</param>
Public Sub ToggleSettings(enabled As Boolean, saveTo As String)
' Read the existing settings from the settings file
Dim json As String = File.ReadAllText(settingsFilePath)
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
' Handle unexpected value of saveTo (if needed)
End If
' Save the updated settings back to the settings file
SaveSettings(settings)
' Apply the updated settings to the application
ApplySettings()
End Sub
End Class

259
RPST GUI/RPST/Windows/AboutBox.Designer.vb generated Normal file
View File

@@ -0,0 +1,259 @@
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class AboutBox
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Dim resources As ComponentModel.ComponentResourceManager = New ComponentModel.ComponentResourceManager(GetType(AboutBox))
PictureBoxLogo = New PictureBox()
LabelProgramName = New Label()
LabelDescription = New Label()
TabControl1 = New TabControl()
TabPageAbout = New TabPage()
LabelCopyright = New Label()
LinkLabelLicense = New LinkLabel()
LinkLabelReadtheWiki = New LinkLabel()
TabPageAuthor = New TabPage()
LinkLabelEmail = New LinkLabel()
LinkLabelBMC = New LinkLabel()
LinkLabelAboutMe = New LinkLabel()
LabelAuthor = New Label()
LabelVersion = New Label()
ButtonClose = New Button()
CType(PictureBoxLogo, ComponentModel.ISupportInitialize).BeginInit()
TabControl1.SuspendLayout()
TabPageAbout.SuspendLayout()
TabPageAuthor.SuspendLayout()
SuspendLayout()
'
' PictureBoxLogo
'
PictureBoxLogo.BackColor = Color.Transparent
PictureBoxLogo.Image = CType(resources.GetObject("PictureBoxLogo.Image"), Image)
PictureBoxLogo.Location = New Point(12, 12)
PictureBoxLogo.Name = "PictureBoxLogo"
PictureBoxLogo.Size = New Size(62, 64)
PictureBoxLogo.SizeMode = PictureBoxSizeMode.StretchImage
PictureBoxLogo.TabIndex = 0
PictureBoxLogo.TabStop = False
'
' LabelProgramName
'
LabelProgramName.AutoSize = True
LabelProgramName.Font = New Font("Segoe UI Semibold", 9.75F, FontStyle.Bold, GraphicsUnit.Point)
LabelProgramName.ForeColor = SystemColors.ControlText
LabelProgramName.Location = New Point(80, 33)
LabelProgramName.Name = "LabelProgramName"
LabelProgramName.Size = New Size(44, 17)
LabelProgramName.TabIndex = 3
LabelProgramName.Text = "Name"
'
' LabelDescription
'
LabelDescription.AutoSize = True
LabelDescription.Font = New Font("Segoe UI", 9F, FontStyle.Regular, GraphicsUnit.Point)
LabelDescription.ForeColor = SystemColors.ControlText
LabelDescription.Location = New Point(6, 7)
LabelDescription.Name = "LabelDescription"
LabelDescription.Size = New Size(67, 15)
LabelDescription.TabIndex = 4
LabelDescription.Text = "Description"
'
' TabControl1
'
TabControl1.Controls.Add(TabPageAbout)
TabControl1.Controls.Add(TabPageAuthor)
TabControl1.Font = New Font("Segoe UI", 9F, FontStyle.Regular, GraphicsUnit.Point)
TabControl1.Location = New Point(12, 91)
TabControl1.Name = "TabControl1"
TabControl1.SelectedIndex = 0
TabControl1.Size = New Size(322, 152)
TabControl1.TabIndex = 8
'
' TabPageAbout
'
TabPageAbout.BackColor = Color.Transparent
TabPageAbout.Controls.Add(LabelCopyright)
TabPageAbout.Controls.Add(LinkLabelLicense)
TabPageAbout.Controls.Add(LabelDescription)
TabPageAbout.Controls.Add(LinkLabelReadtheWiki)
TabPageAbout.Font = New Font("Segoe UI Semibold", 9F, FontStyle.Bold, GraphicsUnit.Point)
TabPageAbout.Location = New Point(4, 24)
TabPageAbout.Name = "TabPageAbout"
TabPageAbout.Padding = New Padding(3)
TabPageAbout.Size = New Size(314, 124)
TabPageAbout.TabIndex = 0
TabPageAbout.Text = "About"
'
' LabelCopyright
'
LabelCopyright.AutoSize = True
LabelCopyright.Font = New Font("Segoe UI", 9F, FontStyle.Regular, GraphicsUnit.Point)
LabelCopyright.Location = New Point(6, 97)
LabelCopyright.Name = "LabelCopyright"
LabelCopyright.Size = New Size(60, 15)
LabelCopyright.TabIndex = 7
LabelCopyright.Text = "Copyright"
'
' LinkLabelLicense
'
LinkLabelLicense.AutoSize = True
LinkLabelLicense.Font = New Font("Segoe UI", 9F, FontStyle.Regular, GraphicsUnit.Point)
LinkLabelLicense.Location = New Point(6, 52)
LinkLabelLicense.Name = "LinkLabelLicense"
LinkLabelLicense.Size = New Size(84, 15)
LinkLabelLicense.TabIndex = 5
LinkLabelLicense.TabStop = True
LinkLabelLicense.Text = "🗒️ MIT License"
'
' LinkLabelReadtheWiki
'
LinkLabelReadtheWiki.AutoSize = True
LinkLabelReadtheWiki.Font = New Font("Segoe UI", 9F, FontStyle.Regular, GraphicsUnit.Point)
LinkLabelReadtheWiki.Location = New Point(6, 74)
LinkLabelReadtheWiki.Name = "LinkLabelReadtheWiki"
LinkLabelReadtheWiki.Size = New Size(94, 15)
LinkLabelReadtheWiki.TabIndex = 6
LinkLabelReadtheWiki.TabStop = True
LinkLabelReadtheWiki.Text = "📖 Read the Wiki"
'
' TabPageAuthor
'
TabPageAuthor.BackColor = Color.Transparent
TabPageAuthor.Controls.Add(LinkLabelEmail)
TabPageAuthor.Controls.Add(LinkLabelBMC)
TabPageAuthor.Controls.Add(LinkLabelAboutMe)
TabPageAuthor.Controls.Add(LabelAuthor)
TabPageAuthor.ForeColor = SystemColors.ControlText
TabPageAuthor.Location = New Point(4, 24)
TabPageAuthor.Name = "TabPageAuthor"
TabPageAuthor.Padding = New Padding(3)
TabPageAuthor.Size = New Size(314, 124)
TabPageAuthor.TabIndex = 1
TabPageAuthor.Text = "Author"
'
' LinkLabelEmail
'
LinkLabelEmail.AutoSize = True
LinkLabelEmail.Location = New Point(6, 89)
LinkLabelEmail.Name = "LinkLabelEmail"
LinkLabelEmail.Size = New Size(51, 15)
LinkLabelEmail.TabIndex = 3
LinkLabelEmail.TabStop = True
LinkLabelEmail.Text = "📧 Email"
'
' LinkLabelBMC
'
LinkLabelBMC.AutoSize = True
LinkLabelBMC.Location = New Point(3, 66)
LinkLabelBMC.Name = "LinkLabelBMC"
LinkLabelBMC.Size = New Size(111, 15)
LinkLabelBMC.TabIndex = 2
LinkLabelBMC.TabStop = True
LinkLabelBMC.Text = "🍵 Buy Me A Coffee"
'
' LinkLabelAboutMe
'
LinkLabelAboutMe.AutoSize = True
LinkLabelAboutMe.Location = New Point(6, 43)
LinkLabelAboutMe.Name = "LinkLabelAboutMe"
LinkLabelAboutMe.Size = New Size(75, 15)
LinkLabelAboutMe.TabIndex = 1
LinkLabelAboutMe.TabStop = True
LinkLabelAboutMe.Text = "🔗 About.me"
'
' LabelAuthor
'
LabelAuthor.AutoSize = True
LabelAuthor.Font = New Font("Segoe UI", 9F, FontStyle.Bold, GraphicsUnit.Point)
LabelAuthor.Location = New Point(6, 15)
LabelAuthor.Name = "LabelAuthor"
LabelAuthor.Size = New Size(96, 15)
LabelAuthor.TabIndex = 0
LabelAuthor.Text = "Richard Mwewa"
'
' LabelVersion
'
LabelVersion.AutoSize = True
LabelVersion.Font = New Font("Segoe UI", 8.25F, FontStyle.Regular, GraphicsUnit.Point)
LabelVersion.Location = New Point(80, 53)
LabelVersion.Name = "LabelVersion"
LabelVersion.Size = New Size(45, 13)
LabelVersion.TabIndex = 9
LabelVersion.Text = "Version"
'
' ButtonClose
'
ButtonClose.Location = New Point(275, 249)
ButtonClose.Name = "ButtonClose"
ButtonClose.Size = New Size(61, 23)
ButtonClose.TabIndex = 6
ButtonClose.Text = "&Close"
ButtonClose.UseVisualStyleBackColor = True
'
' AboutBox
'
AutoScaleDimensions = New SizeF(7F, 15F)
AutoScaleMode = AutoScaleMode.Font
BackColor = Color.Gainsboro
CancelButton = ButtonClose
ClientSize = New Size(346, 285)
Controls.Add(ButtonClose)
Controls.Add(LabelVersion)
Controls.Add(TabControl1)
Controls.Add(LabelProgramName)
Controls.Add(PictureBoxLogo)
FormBorderStyle = FormBorderStyle.FixedSingle
Icon = CType(resources.GetObject("$this.Icon"), Icon)
MaximizeBox = False
MinimizeBox = False
Name = "AboutBox"
ShowInTaskbar = False
StartPosition = FormStartPosition.CenterScreen
Text = "About"
CType(PictureBoxLogo, ComponentModel.ISupportInitialize).EndInit()
TabControl1.ResumeLayout(False)
TabPageAbout.ResumeLayout(False)
TabPageAbout.PerformLayout()
TabPageAuthor.ResumeLayout(False)
TabPageAuthor.PerformLayout()
ResumeLayout(False)
PerformLayout()
End Sub
Friend WithEvents PictureBoxLogo As PictureBox
Friend WithEvents LabelProgramName As Label
Friend WithEvents LabelDescription As Label
Friend WithEvents LicenseRichTextBox As RichTextBox
Friend WithEvents DataGridView1 As DataGridView
Friend WithEvents TabControl1 As TabControl
Friend WithEvents TabPageAbout As TabPage
Friend WithEvents TabPageAuthor As TabPage
Friend WithEvents LabelVersion As Label
Friend WithEvents LinkLabelLicense As LinkLabel
Friend WithEvents ButtonClose As Button
Friend WithEvents LabelCopyright As Label
Friend WithEvents LinkLabelReadtheWiki As LinkLabel
Friend WithEvents LabelAuthor As Label
Friend WithEvents LinkLabelAboutMe As LinkLabel
Friend WithEvents LinkLabelEmail As LinkLabel
Friend WithEvents LinkLabelBMC As LinkLabel
End Class

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,82 @@
Imports System.Runtime
Public Class AboutBox
ReadOnly settings As New SettingsManager()
''' <summary>
''' Handles the Load event for the AboutBox form.
''' </summary>
''' <param name="sender">The source of the event.</param>
''' <param name="e">The event data.</param>
Private Sub AboutBox_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.Text = $"About {My.Application.Info.AssemblyName}"
settings.LoadSettings()
settings.ToggleSettings(settings.DarkMode, "darkmode")
LabelProgramName.Text = My.Application.Info.ProductName
LabelDescription.Text = "Retrieve Reddit posts that contain the specified keyword
from a specified subreddit. "
LabelVersion.Text = $"Version {My.Application.Info.Version}"
LabelCopyright.Text = My.Application.Info.Copyright
End Sub
''' <summary>
''' Handles the LinkClicked event for the LinkLabelLicense control.
''' Opens A MessageBox showing the License Notice.
''' </summary>
''' <param name="sender">The source of the event.</param>
''' <param name="e">The event data.</param>
Private Sub LinkLabelLicense_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) Handles LinkLabelLicense.LinkClicked
Utilities.LicenseAgreement()
End Sub
''' <summary>
''' Handles the LinkClicked event for the LinkLabelReadtheWiki control.
''' Opens the Wiki URL in the default browser.
''' </summary>
''' <param name="sender">The source of the event.</param>
''' <param name="e">The event data.</param>
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")
End Sub
''' <summary>
''' Handles the LinkClicked event for the LinkLabelAboutMe control.
''' Opens A MessageBox showing the License Notice.
''' </summary>
''' <param name="sender">The source of the event.</param>
''' <param name="e">The event data.</param>
Private Sub LinkLabelAboutMe_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) Handles LinkLabelAboutMe.LinkClicked
Shell("cmd /c start https://about.me/rly0nheart")
End Sub
''' <summary>
''' Handles the LinkClicked event for the LinkLabelBMC control.
''' Opens A MessageBox showing the License Notice.
''' </summary>
''' <param name="sender">The source of the event.</param>
''' <param name="e">The event data.</param>
Private Sub LinkLabelBMC_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) Handles LinkLabelBMC.LinkClicked
Shell("cmd /c start https://buymeacoffee.com/_rly0nheart")
End Sub
''' <summary>
''' Handles the LinkClicked event for the LinkLabelEmail control.
''' Opens A MessageBox showing the License Notice.
''' </summary>
''' <param name="sender">The source of the event.</param>
''' <param name="e">The event data.</param>
Private Sub LinkLabelEmail_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) Handles LinkLabelEmail.LinkClicked
Shell("cmd /c start mailto:rly0nheart@duck.com")
End Sub
''' <summary>
''' Handles the Click event for ButtonOK event.
''' </summary>
''' <param name="sender">The source of the event.</param>
''' <param name="e">The event data.</param>
Private Sub ButtonOK_Click(sender As Object, e As EventArgs) Handles ButtonClose.Click
Me.Close()
End Sub
End Class

View File

@@ -1,5 +1,5 @@
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Class FormMain
Partial Class MainWindow
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
@@ -23,10 +23,10 @@ Partial Class FormMain
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
components = New ComponentModel.Container()
Dim resources As ComponentModel.ComponentResourceManager = New ComponentModel.ComponentResourceManager(GetType(FormMain))
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(MainWindow))
TextBoxKeyword = New TextBox()
TextBoxSubreddit = New TextBox()
ButtonScrape = New Button()
ButtonSearch = New Button()
ComboBoxTimeframe = New ComboBox()
ComboBoxListing = New ComboBox()
LabelKeyword = New Label()
@@ -41,7 +41,6 @@ Partial Class FormMain
ToJSONToolStripMenuItem = New ToolStripMenuItem()
ToCSVToolStripMenuItem = New ToolStripMenuItem()
AboutToolStripMenuItem = New ToolStripMenuItem()
DeveloperToolStripMenuItem = New ToolStripMenuItem()
CheckForUpdatesToolStripMenuItem = New ToolStripMenuItem()
QuitToolStripMenuItem = New ToolStripMenuItem()
NumericUpDownLimit = New NumericUpDown()
@@ -70,20 +69,19 @@ Partial Class FormMain
TextBoxSubreddit.TabIndex = 4
ToolTip.SetToolTip(TextBoxSubreddit, "[required] The subreddit to search in.")
'
' ButtonScrape
' ButtonSearch
'
ButtonScrape.Location = New Point(167, 174)
ButtonScrape.Name = "ButtonScrape"
ButtonScrape.Size = New Size(51, 28)
ButtonScrape.TabIndex = 6
ButtonScrape.Text = "Scrape"
ToolTip.SetToolTip(ButtonScrape, "Hitting ENTER will also start the scraping process.")
ButtonScrape.UseVisualStyleBackColor = True
ButtonSearch.Location = New Point(165, 165)
ButtonSearch.Name = "ButtonSearch"
ButtonSearch.Size = New Size(55, 28)
ButtonSearch.TabIndex = 6
ButtonSearch.Text = "Search"
ToolTip.SetToolTip(ButtonSearch, "Hitting ENTER will also start the scraping process.")
ButtonSearch.UseVisualStyleBackColor = True
'
' ComboBoxTimeframe
'
ComboBoxTimeframe.AutoCompleteCustomSource.AddRange(New String() {"Hour", "Day", "Week", "Month", "Year"})
ComboBoxTimeframe.AutoCompleteMode = AutoCompleteMode.Append
ComboBoxTimeframe.AutoCompleteSource = AutoCompleteSource.CustomSource
ComboBoxTimeframe.FormattingEnabled = True
ComboBoxTimeframe.Items.AddRange(New Object() {"Hour", "Day", "Week", "Month", "Year"})
@@ -97,8 +95,8 @@ Partial Class FormMain
' ComboBoxListing
'
ComboBoxListing.AutoCompleteCustomSource.AddRange(New String() {"Controversial", "Hot", "Best", "New", "Rising"})
ComboBoxListing.AutoCompleteMode = AutoCompleteMode.Append
ComboBoxListing.AutoCompleteSource = AutoCompleteSource.CustomSource
ComboBoxListing.BackColor = SystemColors.Window
ComboBoxListing.FormattingEnabled = True
ComboBoxListing.Items.AddRange(New Object() {"Controversial", "Hot", "Best", "New", "Rising"})
ComboBoxListing.Location = New Point(118, 107)
@@ -165,9 +163,9 @@ Partial Class FormMain
'
' ContextMenuStripRightClick
'
ContextMenuStripRightClick.Items.AddRange(New ToolStripItem() {AboutToolStripMenuItem, DeveloperToolStripMenuItem, CheckForUpdatesToolStripMenuItem, SettingsToolStripMenuItem, QuitToolStripMenuItem})
ContextMenuStripRightClick.Items.AddRange(New ToolStripItem() {SettingsToolStripMenuItem, AboutToolStripMenuItem, CheckForUpdatesToolStripMenuItem, QuitToolStripMenuItem})
ContextMenuStripRightClick.Name = "ContextMenuStrip1"
ContextMenuStripRightClick.Size = New Size(172, 114)
ContextMenuStripRightClick.Size = New Size(172, 92)
'
' SettingsToolStripMenuItem
'
@@ -182,7 +180,7 @@ Partial Class FormMain
DarkModeToolStripMenuItem.CheckOnClick = True
DarkModeToolStripMenuItem.Image = CType(resources.GetObject("DarkModeToolStripMenuItem.Image"), Image)
DarkModeToolStripMenuItem.Name = "DarkModeToolStripMenuItem"
DarkModeToolStripMenuItem.Size = New Size(180, 22)
DarkModeToolStripMenuItem.Size = New Size(132, 22)
DarkModeToolStripMenuItem.Text = "Dark Mode"
'
' SavePostsToolStripMenuItem
@@ -191,7 +189,7 @@ Partial Class FormMain
SavePostsToolStripMenuItem.DropDownItems.AddRange(New ToolStripItem() {ToJSONToolStripMenuItem, ToCSVToolStripMenuItem})
SavePostsToolStripMenuItem.Image = CType(resources.GetObject("SavePostsToolStripMenuItem.Image"), Image)
SavePostsToolStripMenuItem.Name = "SavePostsToolStripMenuItem"
SavePostsToolStripMenuItem.Size = New Size(180, 22)
SavePostsToolStripMenuItem.Size = New Size(132, 22)
SavePostsToolStripMenuItem.Text = "Save posts"
'
' ToJSONToolStripMenuItem
@@ -200,7 +198,7 @@ Partial Class FormMain
ToJSONToolStripMenuItem.CheckOnClick = True
ToJSONToolStripMenuItem.Image = CType(resources.GetObject("ToJSONToolStripMenuItem.Image"), Image)
ToJSONToolStripMenuItem.Name = "ToJSONToolStripMenuItem"
ToJSONToolStripMenuItem.Size = New Size(180, 22)
ToJSONToolStripMenuItem.Size = New Size(116, 22)
ToJSONToolStripMenuItem.Text = "to JSON"
'
' ToCSVToolStripMenuItem
@@ -209,7 +207,7 @@ Partial Class FormMain
ToCSVToolStripMenuItem.CheckOnClick = True
ToCSVToolStripMenuItem.Image = CType(resources.GetObject("ToCSVToolStripMenuItem.Image"), Image)
ToCSVToolStripMenuItem.Name = "ToCSVToolStripMenuItem"
ToCSVToolStripMenuItem.Size = New Size(180, 22)
ToCSVToolStripMenuItem.Size = New Size(116, 22)
ToCSVToolStripMenuItem.Text = "to CSV"
'
' AboutToolStripMenuItem
@@ -218,15 +216,7 @@ Partial Class FormMain
AboutToolStripMenuItem.Image = CType(resources.GetObject("AboutToolStripMenuItem.Image"), Image)
AboutToolStripMenuItem.Name = "AboutToolStripMenuItem"
AboutToolStripMenuItem.Size = New Size(171, 22)
AboutToolStripMenuItem.Text = "About"
'
' DeveloperToolStripMenuItem
'
DeveloperToolStripMenuItem.AutoToolTip = True
DeveloperToolStripMenuItem.Image = CType(resources.GetObject("DeveloperToolStripMenuItem.Image"), Image)
DeveloperToolStripMenuItem.Name = "DeveloperToolStripMenuItem"
DeveloperToolStripMenuItem.Size = New Size(171, 22)
DeveloperToolStripMenuItem.Text = "Developer"
AboutToolStripMenuItem.Text = "About RPST"
'
' CheckForUpdatesToolStripMenuItem
'
@@ -248,13 +238,14 @@ Partial Class FormMain
' NumericUpDownLimit
'
NumericUpDownLimit.Location = New Point(118, 78)
NumericUpDownLimit.Minimum = New Decimal(New Integer() {5, 0, 0, 0})
NumericUpDownLimit.Maximum = New Decimal(New Integer() {10000, 0, 0, 0})
NumericUpDownLimit.Minimum = New Decimal(New Integer() {200, 0, 0, 0})
NumericUpDownLimit.Name = "NumericUpDownLimit"
NumericUpDownLimit.ReadOnly = True
NumericUpDownLimit.Size = New Size(100, 23)
NumericUpDownLimit.TabIndex = 15
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() {200, 0, 0, 0})
'
' ToolTip
'
@@ -265,12 +256,12 @@ Partial Class FormMain
ToolTip.ToolTipIcon = ToolTipIcon.Info
ToolTip.ToolTipTitle = "Tip"
'
' FormMain
' MainWindow
'
AutoScaleDimensions = New SizeF(7F, 15F)
AutoScaleMode = AutoScaleMode.Font
BackColor = SystemColors.Control
ClientSize = New Size(239, 221)
ClientSize = New Size(239, 211)
ContextMenuStrip = ContextMenuStripRightClick
Controls.Add(ComboBoxTimeframe)
Controls.Add(TextBoxKeyword)
@@ -279,14 +270,14 @@ Partial Class FormMain
Controls.Add(ComboBoxListing)
Controls.Add(NumericUpDownLimit)
Controls.Add(LabelListing)
Controls.Add(ButtonScrape)
Controls.Add(ButtonSearch)
Controls.Add(LabelLimit)
Controls.Add(LabelSubreddit)
Controls.Add(TextBoxSubreddit)
FormBorderStyle = FormBorderStyle.FixedSingle
Icon = CType(resources.GetObject("$this.Icon"), Icon)
MaximizeBox = False
Name = "FormMain"
Name = "MainWindow"
StartPosition = FormStartPosition.CenterScreen
Text = "RPST"
ContextMenuStripRightClick.ResumeLayout(False)
@@ -297,7 +288,7 @@ Partial Class FormMain
Friend WithEvents TextBoxKeyword As TextBox
Friend WithEvents TextBoxSubreddit As TextBox
Friend WithEvents ButtonScrape As Button
Friend WithEvents ButtonSearch As Button
Friend WithEvents ComboBoxTimeframe As ComboBox
Friend WithEvents ComboBoxListing As ComboBox
Friend WithEvents LabelKeyword As Label
@@ -311,7 +302,6 @@ Partial Class FormMain
Friend WithEvents ToCSVToolStripMenuItem As ToolStripMenuItem
Friend WithEvents NumericUpDownLimit As NumericUpDown
Friend WithEvents AboutToolStripMenuItem As ToolStripMenuItem
Friend WithEvents DeveloperToolStripMenuItem As ToolStripMenuItem
Friend WithEvents CheckForUpdatesToolStripMenuItem As ToolStripMenuItem
Friend WithEvents QuitToolStripMenuItem As ToolStripMenuItem
Friend WithEvents ToolTip As ToolTip

View File

@@ -1,6 +1,6 @@
Imports Newtonsoft.Json.Linq
Public Class FormMain
Public Class MainWindow
ReadOnly settings As New SettingsManager()
ReadOnly ApiHandler As New ApiHandler()
@@ -10,15 +10,14 @@ Public Class FormMain
''' </summary>
''' <param name="sender">The source of the event.</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 MainWindow_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Utilities.PathFinder()
settings.LoadSettings()
settings.ToggleSettings(settings.DarkMode, "darkmode")
settings.ToggleSettings(settings.SaveToJson, "json")
settings.ToggleSettings(settings.SaveToCsv, "csv")
settings.ToggleSettings(enabled:=settings.DarkMode, saveTo:="darkmode")
settings.ToggleSettings(enabled:=settings.SaveToJson, saveTo:="json")
settings.ToggleSettings(enabled:=settings.SaveToCsv, saveTo:="csv")
Utilities.PathFinder()
Utilities.LogFirstTimeLaunch()
Me.Text = My.Application.Info.AssemblyName
End Sub
@@ -34,32 +33,21 @@ Public Class FormMain
End Sub
''' <summary>
''' Event handler for the 'Developer' menu item click.
''' It shows the 'Developer' dialog box.
''' </summary>
''' <param name="sender">The source of the event.</param>
''' <param name="e">An EventArgs that contains the event data.</param>
Private Sub ToolStripMenuItemDeveloper_Click(sender As Object, e As EventArgs) Handles DeveloperToolStripMenuItem.Click
DeveloperBox.ShowDialog()
End Sub
''' <summary>
''' Event handler for the 'Check Updates' menu item click.
''' It checks for application updates and provides update information if a newer version is available.
''' </summary>
''' <param name="sender">The source of the event.</param>
''' <param name="e">An EventArgs that contains the event data.</param>
Private Sub ToolStripMenuItemCheckUpdates_Click(sender As Object, e As EventArgs) Handles CheckForUpdatesToolStripMenuItem.Click
Dim data As JObject = ApiHandler.CheckUpdates()
Private Async Sub ToolStripMenuItemCheckUpdates_Click(sender As Object, e As EventArgs) Handles CheckForUpdatesToolStripMenuItem.Click
Dim data As JObject = Await ApiHandler.CheckUpdatesAsync()
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)
Else
Dim confirm As DialogResult = MessageBox.Show($"A new version v{data("tag_name")} of {Me.Text} is available, would you like to get it?
{data("body")}
", $"{Me.Text} v{data("tag_name")}".ToString, MessageBoxButtons.YesNo, MessageBoxIcon.Question)
", $"{Me.Text} v{data("tag_name")}", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If confirm = DialogResult.Yes Then
Shell($"cmd /c start {data("html_url")}")
End If
@@ -88,7 +76,7 @@ Public Class FormMain
''' </summary>
''' <param name="sender">The sender of the event.</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 ButtonSearch.Click
settings.LoadSettings()
PostsProcessor.ProcessRedditPosts(settings:=settings)
End Sub
@@ -190,7 +178,7 @@ Public Class FormMain
''' <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")
settings.ToggleSettings(enabled:=DarkModeToolStripMenuItem.Checked, saveTo:="darkmode")
End Sub
''' <summary>
@@ -200,7 +188,7 @@ Public Class FormMain
''' <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")
settings.ToggleSettings(enabled:=ToCSVToolStripMenuItem.Checked, saveTo:="csv")
End Sub
''' <summary>
@@ -210,6 +198,6 @@ Public Class FormMain
''' <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")
settings.ToggleSettings(enabled:=ToJSONToolStripMenuItem.Checked, saveTo:="json")
End Sub
End Class

View File

@@ -0,0 +1,203 @@
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Class PostsWindow
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()>
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(PostsWindow))
DataGridViewPosts = New DataGridView()
postIndex = New DataGridViewTextBoxColumn()
postAuthor = New DataGridViewTextBoxColumn()
postId = New DataGridViewTextBoxColumn()
postTitle = New DataGridViewTextBoxColumn()
postText = New DataGridViewTextBoxColumn()
postSubreddit = New DataGridViewTextBoxColumn()
postSubredditType = New DataGridViewTextBoxColumn()
postThumbnail = New DataGridViewTextBoxColumn()
postIsNSFW = New DataGridViewTextBoxColumn()
postIsGilded = New DataGridViewTextBoxColumn()
postUpvotes = New DataGridViewTextBoxColumn()
postUpvoteRatio = New DataGridViewTextBoxColumn()
postIsShareable = New DataGridViewTextBoxColumn()
postScore = New DataGridViewTextBoxColumn()
postCategory = New DataGridViewTextBoxColumn()
postDomain = New DataGridViewTextBoxColumn()
postPermalink = New DataGridViewTextBoxColumn()
postCreatedAt = New DataGridViewTextBoxColumn()
CType(DataGridViewPosts, ComponentModel.ISupportInitialize).BeginInit()
SuspendLayout()
'
' DataGridViewPosts
'
DataGridViewPosts.BackgroundColor = Color.Gainsboro
DataGridViewPosts.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize
DataGridViewPosts.Columns.AddRange(New DataGridViewColumn() {postIndex, postAuthor, postId, postTitle, postText, postSubreddit, postSubredditType, postThumbnail, postIsNSFW, postIsGilded, postUpvotes, postUpvoteRatio, postIsShareable, postScore, postCategory, postDomain, postPermalink, postCreatedAt})
DataGridViewPosts.Dock = DockStyle.Fill
DataGridViewPosts.Location = New Point(0, 0)
DataGridViewPosts.Name = "DataGridViewPosts"
DataGridViewPosts.ReadOnly = True
DataGridViewPosts.RowHeadersVisible = False
DataGridViewPosts.RowTemplate.Height = 25
DataGridViewPosts.Size = New Size(501, 365)
DataGridViewPosts.TabIndex = 3
'
' postIndex
'
postIndex.HeaderText = "Index"
postIndex.Name = "postIndex"
postIndex.ReadOnly = True
'
' postAuthor
'
postAuthor.HeaderText = "Author"
postAuthor.Name = "postAuthor"
postAuthor.ReadOnly = True
'
' postId
'
postId.HeaderText = "ID"
postId.Name = "postId"
postId.ReadOnly = True
'
' postTitle
'
postTitle.HeaderText = "Title"
postTitle.Name = "postTitle"
postTitle.ReadOnly = True
'
' postText
'
postText.HeaderText = "Text"
postText.Name = "postText"
postText.ReadOnly = True
'
' postSubreddit
'
postSubreddit.HeaderText = "Subreddit"
postSubreddit.Name = "postSubreddit"
postSubreddit.ReadOnly = True
'
' postSubredditType
'
postSubredditType.HeaderText = "Subreddit Type"
postSubredditType.Name = "postSubredditType"
postSubredditType.ReadOnly = True
'
' postThumbnail
'
postThumbnail.HeaderText = "Thumbnail"
postThumbnail.Name = "postThumbnail"
postThumbnail.ReadOnly = True
'
' postIsNSFW
'
postIsNSFW.HeaderText = "Is NSFW"
postIsNSFW.Name = "postIsNSFW"
postIsNSFW.ReadOnly = True
'
' postIsGilded
'
postIsGilded.HeaderText = "Is Gilded"
postIsGilded.Name = "postIsGilded"
postIsGilded.ReadOnly = True
'
' postUpvotes
'
postUpvotes.HeaderText = "Upvotes"
postUpvotes.Name = "postUpvotes"
postUpvotes.ReadOnly = True
'
' postUpvoteRatio
'
postUpvoteRatio.HeaderText = "Upvote Ratio"
postUpvoteRatio.Name = "postUpvoteRatio"
postUpvoteRatio.ReadOnly = True
'
' postIsShareable
'
postIsShareable.HeaderText = "Is Shareable"
postIsShareable.Name = "postIsShareable"
postIsShareable.ReadOnly = True
'
' postScore
'
postScore.HeaderText = "Score"
postScore.Name = "postScore"
postScore.ReadOnly = True
'
' postCategory
'
postCategory.HeaderText = "Category"
postCategory.Name = "postCategory"
postCategory.ReadOnly = True
'
' postDomain
'
postDomain.HeaderText = "Domain"
postDomain.Name = "postDomain"
postDomain.ReadOnly = True
'
' postPermalink
'
postPermalink.HeaderText = "Permalink"
postPermalink.Name = "postPermalink"
postPermalink.ReadOnly = True
'
' postCreatedAt
'
postCreatedAt.HeaderText = "Created At"
postCreatedAt.Name = "postCreatedAt"
postCreatedAt.ReadOnly = True
'
' PostsWindow
'
AutoScaleDimensions = New SizeF(7F, 15F)
AutoScaleMode = AutoScaleMode.Font
ClientSize = New Size(501, 365)
Controls.Add(DataGridViewPosts)
Icon = CType(resources.GetObject("$this.Icon"), Icon)
Name = "PostsWindow"
StartPosition = FormStartPosition.CenterScreen
Text = "Posts"
CType(DataGridViewPosts, ComponentModel.ISupportInitialize).EndInit()
ResumeLayout(False)
End Sub
Friend WithEvents DataGridViewPosts As DataGridView
Friend WithEvents postIndex As DataGridViewTextBoxColumn
Friend WithEvents postAuthor As DataGridViewTextBoxColumn
Friend WithEvents postId As DataGridViewTextBoxColumn
Friend WithEvents postTitle As DataGridViewTextBoxColumn
Friend WithEvents postText As DataGridViewTextBoxColumn
Friend WithEvents postSubreddit As DataGridViewTextBoxColumn
Friend WithEvents postSubredditType As DataGridViewTextBoxColumn
Friend WithEvents postThumbnail As DataGridViewTextBoxColumn
Friend WithEvents postIsNSFW As DataGridViewTextBoxColumn
Friend WithEvents postIsGilded As DataGridViewTextBoxColumn
Friend WithEvents postUpvotes As DataGridViewTextBoxColumn
Friend WithEvents postUpvoteRatio As DataGridViewTextBoxColumn
Friend WithEvents postIsShareable As DataGridViewTextBoxColumn
Friend WithEvents postScore As DataGridViewTextBoxColumn
Friend WithEvents postCategory As DataGridViewTextBoxColumn
Friend WithEvents postDomain As DataGridViewTextBoxColumn
Friend WithEvents postPermalink As DataGridViewTextBoxColumn
Friend WithEvents postCreatedAt As DataGridViewTextBoxColumn
End Class

View File

@@ -0,0 +1,622 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, 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="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="postIndex.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="postAuthor.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="postId.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="postTitle.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="postText.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="postSubreddit.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="postSubredditType.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="postThumbnail.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="postIsNSFW.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="postIsGilded.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="postUpvotes.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="postUpvoteRatio.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="postIsShareable.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="postScore.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="postCategory.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="postDomain.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="postPermalink.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="postCreatedAt.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
8DXKzC//H2KEQtrPXsHrAAAAAElFTkSuQmCC
</value>
</data>
</root>

View File

@@ -0,0 +1,3 @@
Public Class PostsWindow
End Class

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -0,0 +1,792 @@
"DeployProject"
{
"VSVersion" = "3:800"
"ProjectType" = "8:{978C614F-708E-4E1A-B201-565925725DBA}"
"IsWebType" = "8:FALSE"
"ProjectName" = "8:RPSTSetup"
"LanguageId" = "3:0"
"CodePage" = "3:1252"
"UILanguageId" = "3:0"
"SccProjectName" = "8:"
"SccLocalPath" = "8:"
"SccAuxPath" = "8:"
"SccProvider" = "8:"
"Hierarchy"
{
"Entry"
{
"MsmKey" = "8:_3E2A5BCE69FF40C19B380CE7DE18F582"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_68E75ECCCEB74C9DAEE029419E7ACA2B"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_76F301ADC81F41699FE5F6EFEFECAA11"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
}
"Configurations"
{
"Debug"
{
"DisplayName" = "8:Debug"
"IsDebugOnly" = "11:TRUE"
"IsReleaseOnly" = "11:FALSE"
"OutputFilename" = "8:Debug\\RPSTSetup.msi"
"PackageFilesAs" = "3:2"
"PackageFileSize" = "3:-2147483648"
"CabType" = "3:1"
"Compression" = "3:2"
"SignOutput" = "11:FALSE"
"CertificateFile" = "8:"
"PrivateKeyFile" = "8:"
"TimeStampServer" = "8:"
"InstallerBootstrapper" = "3:2"
"BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}"
{
"Enabled" = "11:TRUE"
"PromptEnabled" = "11:TRUE"
"PrerequisitesLocation" = "2:1"
"Url" = "8:"
"ComponentsUrl" = "8:"
"Items"
{
"{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.NetCore.CoreRuntime.6.0.x64"
{
"Name" = "8:.NET Runtime 6.0.25 (x64)"
"ProductCode" = "8:Microsoft.NetCore.CoreRuntime.6.0.x64"
}
"{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.NetCore.CoreRuntime.6.0.x86"
{
"Name" = "8:.NET Runtime 6.0.25 (x86)"
"ProductCode" = "8:Microsoft.NetCore.CoreRuntime.6.0.x86"
}
}
}
}
"Release"
{
"DisplayName" = "8:Release"
"IsDebugOnly" = "11:FALSE"
"IsReleaseOnly" = "11:TRUE"
"OutputFilename" = "8:Release\\RPSTSetup.msi"
"PackageFilesAs" = "3:2"
"PackageFileSize" = "3:-2147483648"
"CabType" = "3:1"
"Compression" = "3:2"
"SignOutput" = "11:FALSE"
"CertificateFile" = "8:"
"PrivateKeyFile" = "8:"
"TimeStampServer" = "8:"
"InstallerBootstrapper" = "3:2"
}
}
"Deployable"
{
"CustomAction"
{
}
"DefaultFeature"
{
"Name" = "8:DefaultFeature"
"Title" = "8:"
"Description" = "8:"
}
"ExternalPersistence"
{
"LaunchCondition"
{
"{A06ECF26-33A3-4562-8140-9B0E340D4F24}:_17213E668C074AD5AD5FC8E06206E69E"
{
"Name" = "8:.NET Core"
"Message" = "8:[VSDNETCOREMSG]"
"AllowLaterVersions" = "11:FALSE"
"InstallUrl" = "8:https://dotnet.microsoft.com/download/dotnet-core/[NetCoreVerMajorDotMinor]"
"IsNETCore" = "11:TRUE"
"Architecture" = "2:0"
"Runtime" = "2:0"
}
}
}
"File"
{
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3E2A5BCE69FF40C19B380CE7DE18F582"
{
"SourcePath" = "8:..\\RPST\\Resources\\icon-small.ico"
"TargetName" = "8:icon-small.ico"
"Tag" = "8:"
"Folder" = "8:_362735941ABB4269A087A0EAC1F3EB41"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:TRUE"
"Hidden" = "11:TRUE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_76F301ADC81F41699FE5F6EFEFECAA11"
{
"SourcePath" = "8:..\\RPST\\LICENSE.rtf"
"TargetName" = "8:LICENSE.rtf"
"Tag" = "8:"
"Folder" = "8:_362735941ABB4269A087A0EAC1F3EB41"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:TRUE"
"Hidden" = "11:TRUE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
}
"FileType"
{
}
"Folder"
{
"{1525181F-901A-416C-8A58-119130FE478E}:_14AD380FC0AA495FB87400E478966DD2"
{
"Name" = "8:#1919"
"AlwaysCreate" = "11:TRUE"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Property" = "8:ProgramMenuFolder"
"Folders"
{
}
}
"{3C67513D-01DD-4637-8A68-80971EB9504F}:_362735941ABB4269A087A0EAC1F3EB41"
{
"DefaultLocation" = "8:[ProgramFilesFolder][Manufacturer]\\[ProductName]"
"Name" = "8:#1925"
"AlwaysCreate" = "11:FALSE"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Property" = "8:TARGETDIR"
"Folders"
{
}
}
"{1525181F-901A-416C-8A58-119130FE478E}:_BD020B7E2C9F475083F2EE7493C6CA56"
{
"Name" = "8:#1916"
"AlwaysCreate" = "11:TRUE"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Property" = "8:DesktopFolder"
"Folders"
{
}
}
}
"LaunchCondition"
{
}
"Locator"
{
}
"MsiBootstrapper"
{
"LangId" = "3:0"
"RequiresElevation" = "11:FALSE"
}
"Product"
{
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:RPST (Reddit Post Scraping Tool)"
"ProductCode" = "8:{76E86D3A-14D8-426B-ADB6-C22C3D444E49}"
"PackageCode" = "8:{D33BBB6A-B9C1-4596-A299-931B9FEE6921}"
"UpgradeCode" = "8:{05EF97C6-762C-4254-94FF-53380A799007}"
"AspNetVersion" = "8:4.0.30319.0"
"RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:TRUE"
"InstallAllUsers" = "11:FALSE"
"ProductVersion" = "8:2.0.0"
"Manufacturer" = "8:Richard Mwewa"
"ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:https://github.com/bellingcat/reddit-post-scraping-tool/wiki"
"Title" = "8:RPST (Reddit Post Scraping Tool)"
"Subject" = "8:"
"ARPCONTACT" = "8:Richard Mwewa"
"Keywords" = "8:"
"ARPCOMMENTS" = "8:Retrieve Reddit posts that contain the specified keyword from a specified subreddit."
"ARPURLINFOABOUT" = "8:https://about.me/rly0nheart"
"ARPPRODUCTICON" = "8:_3E2A5BCE69FF40C19B380CE7DE18F582"
"ARPIconIndex" = "3:0"
"SearchPath" = "8:"
"UseSystemSearchPath" = "11:TRUE"
"TargetPlatform" = "3:0"
"PreBuildEvent" = "8:"
"PostBuildEvent" = "8:"
"RunPostBuildEvent" = "3:0"
}
"Registry"
{
"HKLM"
{
"Keys"
{
"{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_49885B940CB4489B9981836DE0A26E07"
{
"Name" = "8:Software"
"Condition" = "8:"
"AlwaysCreate" = "11:FALSE"
"DeleteAtUninstall" = "11:FALSE"
"Transitive" = "11:FALSE"
"Keys"
{
"{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_E3E857007AC8478B9D0C9C009F6A8BAF"
{
"Name" = "8:[Manufacturer]"
"Condition" = "8:"
"AlwaysCreate" = "11:FALSE"
"DeleteAtUninstall" = "11:FALSE"
"Transitive" = "11:FALSE"
"Keys"
{
}
"Values"
{
}
}
}
"Values"
{
}
}
}
}
"HKCU"
{
"Keys"
{
"{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_17B8420A2F55464D8FD66D76E90FE530"
{
"Name" = "8:Software"
"Condition" = "8:"
"AlwaysCreate" = "11:FALSE"
"DeleteAtUninstall" = "11:FALSE"
"Transitive" = "11:FALSE"
"Keys"
{
"{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_247BBD924EA946C0B4F05A907A48C9D5"
{
"Name" = "8:[Manufacturer]"
"Condition" = "8:"
"AlwaysCreate" = "11:FALSE"
"DeleteAtUninstall" = "11:FALSE"
"Transitive" = "11:FALSE"
"Keys"
{
}
"Values"
{
}
}
}
"Values"
{
}
}
}
}
"HKCR"
{
"Keys"
{
}
}
"HKU"
{
"Keys"
{
}
}
"HKPU"
{
"Keys"
{
}
}
}
"Sequences"
{
}
"Shortcut"
{
"{970C0BB2-C7D0-45D7-ABFA-7EC378858BC0}:_03274DE5011840E682E398A86F5A065D"
{
"Name" = "8:RPST (Reddit Post Scraping Tool)"
"Arguments" = "8:"
"Description" = "8:Retrieve Reddit posts that contain the specified keyword from a specified subreddit."
"ShowCmd" = "3:1"
"IconIndex" = "3:0"
"Transitive" = "11:FALSE"
"Target" = "8:_68E75ECCCEB74C9DAEE029419E7ACA2B"
"Folder" = "8:_14AD380FC0AA495FB87400E478966DD2"
"WorkingFolder" = "8:_362735941ABB4269A087A0EAC1F3EB41"
"Icon" = "8:_3E2A5BCE69FF40C19B380CE7DE18F582"
"Feature" = "8:"
}
"{970C0BB2-C7D0-45D7-ABFA-7EC378858BC0}:_6C793AC49B71464FA40CB4D6C361BD84"
{
"Name" = "8:RPST (Reddit Post Scraping Tool)"
"Arguments" = "8:"
"Description" = "8:Retrieve Reddit posts that contain the specified keyword from a specified subreddit."
"ShowCmd" = "3:1"
"IconIndex" = "3:0"
"Transitive" = "11:FALSE"
"Target" = "8:_68E75ECCCEB74C9DAEE029419E7ACA2B"
"Folder" = "8:_BD020B7E2C9F475083F2EE7493C6CA56"
"WorkingFolder" = "8:_362735941ABB4269A087A0EAC1F3EB41"
"Icon" = "8:_3E2A5BCE69FF40C19B380CE7DE18F582"
"Feature" = "8:"
}
}
"UserInterface"
{
"{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_260F17414CD94855B1C4E94459527B0E"
{
"UseDynamicProperties" = "11:FALSE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdUserInterface.wim"
}
"{DF760B10-853B-4699-99F2-AFF7185B4A62}:_2E6A77A8635449DCAA91FDB47AD57928"
{
"Name" = "8:#1900"
"Sequence" = "3:2"
"Attributes" = "3:1"
"Dialogs"
{
"{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_318D351DD1CD404E8A4BD093773AE2F5"
{
"Sequence" = "3:100"
"DisplayName" = "8:License Agreement"
"UseDynamicProperties" = "11:TRUE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdAdminLicenseDlg.wid"
"Properties"
{
"BannerBitmap"
{
"Name" = "8:BannerBitmap"
"DisplayName" = "8:#1001"
"Description" = "8:#1101"
"Type" = "3:8"
"ContextData" = "8:Bitmap"
"Attributes" = "3:4"
"Setting" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
"EulaText"
{
"Name" = "8:EulaText"
"DisplayName" = "8:#1008"
"Description" = "8:#1108"
"Type" = "3:6"
"ContextData" = "8:"
"Attributes" = "3:0"
"Setting" = "3:2"
"Value" = "8:_76F301ADC81F41699FE5F6EFEFECAA11"
"UsePlugInResources" = "11:TRUE"
}
"Sunken"
{
"Name" = "8:Sunken"
"DisplayName" = "8:#1007"
"Description" = "8:#1107"
"Type" = "3:5"
"ContextData" = "8:4;True=4;False=0"
"Attributes" = "3:0"
"Setting" = "3:0"
"Value" = "3:4"
"DefaultValue" = "3:4"
"UsePlugInResources" = "11:TRUE"
}
}
}
"{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_5F8575AA5ECB4174B1C60F9DBFBC9855"
{
"Sequence" = "3:200"
"DisplayName" = "8:Installation Folder"
"UseDynamicProperties" = "11:TRUE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdAdminFolderDlg.wid"
"Properties"
{
"BannerBitmap"
{
"Name" = "8:BannerBitmap"
"DisplayName" = "8:#1001"
"Description" = "8:#1101"
"Type" = "3:8"
"ContextData" = "8:Bitmap"
"Attributes" = "3:4"
"Setting" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
}
}
"{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_7D142C585EE6498DA19A25EEBEDACFF6"
{
"Sequence" = "3:300"
"DisplayName" = "8:Confirm Installation"
"UseDynamicProperties" = "11:TRUE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdAdminConfirmDlg.wid"
"Properties"
{
"BannerBitmap"
{
"Name" = "8:BannerBitmap"
"DisplayName" = "8:#1001"
"Description" = "8:#1101"
"Type" = "3:8"
"ContextData" = "8:Bitmap"
"Attributes" = "3:4"
"Setting" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
}
}
}
}
"{DF760B10-853B-4699-99F2-AFF7185B4A62}:_521CEA4C4D36467CAF5E9B792033EB4B"
{
"Name" = "8:#1901"
"Sequence" = "3:2"
"Attributes" = "3:2"
"Dialogs"
{
"{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_80EEC0D3EB6146438998401A4D904E1A"
{
"Sequence" = "3:100"
"DisplayName" = "8:Progress"
"UseDynamicProperties" = "11:TRUE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdAdminProgressDlg.wid"
"Properties"
{
"BannerBitmap"
{
"Name" = "8:BannerBitmap"
"DisplayName" = "8:#1001"
"Description" = "8:#1101"
"Type" = "3:8"
"ContextData" = "8:Bitmap"
"Attributes" = "3:4"
"Setting" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
"ShowProgress"
{
"Name" = "8:ShowProgress"
"DisplayName" = "8:#1009"
"Description" = "8:#1109"
"Type" = "3:5"
"ContextData" = "8:1;True=1;False=0"
"Attributes" = "3:0"
"Setting" = "3:0"
"Value" = "3:1"
"DefaultValue" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
}
}
}
}
"{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_5EFCFC798BF24EB68DC201E4505F8489"
{
"UseDynamicProperties" = "11:FALSE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdBasicDialogs.wim"
}
"{DF760B10-853B-4699-99F2-AFF7185B4A62}:_6BFF4405824D471EA651E90715AAACDF"
{
"Name" = "8:#1901"
"Sequence" = "3:1"
"Attributes" = "3:2"
"Dialogs"
{
"{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_D34EDE0B30824A01B0B266B6079C8469"
{
"Sequence" = "3:100"
"DisplayName" = "8:Progress"
"UseDynamicProperties" = "11:TRUE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdProgressDlg.wid"
"Properties"
{
"BannerBitmap"
{
"Name" = "8:BannerBitmap"
"DisplayName" = "8:#1001"
"Description" = "8:#1101"
"Type" = "3:8"
"ContextData" = "8:Bitmap"
"Attributes" = "3:4"
"Setting" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
"ShowProgress"
{
"Name" = "8:ShowProgress"
"DisplayName" = "8:#1009"
"Description" = "8:#1109"
"Type" = "3:5"
"ContextData" = "8:1;True=1;False=0"
"Attributes" = "3:0"
"Setting" = "3:0"
"Value" = "3:1"
"DefaultValue" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
}
}
}
}
"{DF760B10-853B-4699-99F2-AFF7185B4A62}:_D30397AD6E1547799AC7430D693FA0FC"
{
"Name" = "8:#1902"
"Sequence" = "3:1"
"Attributes" = "3:3"
"Dialogs"
{
"{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_71B305AEDF384563B2D30069B0F145DF"
{
"Sequence" = "3:100"
"DisplayName" = "8:Finished"
"UseDynamicProperties" = "11:TRUE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdFinishedDlg.wid"
"Properties"
{
"BannerBitmap"
{
"Name" = "8:BannerBitmap"
"DisplayName" = "8:#1001"
"Description" = "8:#1101"
"Type" = "3:8"
"ContextData" = "8:Bitmap"
"Attributes" = "3:4"
"Setting" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
"UpdateText"
{
"Name" = "8:UpdateText"
"DisplayName" = "8:#1058"
"Description" = "8:#1158"
"Type" = "3:15"
"ContextData" = "8:"
"Attributes" = "3:0"
"Setting" = "3:1"
"Value" = "8:#1258"
"DefaultValue" = "8:#1258"
"UsePlugInResources" = "11:TRUE"
}
}
}
}
}
"{DF760B10-853B-4699-99F2-AFF7185B4A62}:_EBE4314B289A4ECEB75F0B5D00905DB4"
{
"Name" = "8:#1900"
"Sequence" = "3:1"
"Attributes" = "3:1"
"Dialogs"
{
"{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_5A069E8C7FE74313BA59FE93ED3B017D"
{
"Sequence" = "3:200"
"DisplayName" = "8:License Agreement"
"UseDynamicProperties" = "11:TRUE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdLicenseDlg.wid"
"Properties"
{
"BannerBitmap"
{
"Name" = "8:BannerBitmap"
"DisplayName" = "8:#1001"
"Description" = "8:#1101"
"Type" = "3:8"
"ContextData" = "8:Bitmap"
"Attributes" = "3:4"
"Setting" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
"EulaText"
{
"Name" = "8:EulaText"
"DisplayName" = "8:#1008"
"Description" = "8:#1108"
"Type" = "3:6"
"ContextData" = "8:"
"Attributes" = "3:0"
"Setting" = "3:2"
"Value" = "8:_76F301ADC81F41699FE5F6EFEFECAA11"
"UsePlugInResources" = "11:TRUE"
}
"Sunken"
{
"Name" = "8:Sunken"
"DisplayName" = "8:#1007"
"Description" = "8:#1107"
"Type" = "3:5"
"ContextData" = "8:4;True=4;False=0"
"Attributes" = "3:0"
"Setting" = "3:0"
"Value" = "3:4"
"DefaultValue" = "3:4"
"UsePlugInResources" = "11:TRUE"
}
}
}
"{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_69D777B0C6974DD0AFA54BDF51755C81"
{
"Sequence" = "3:400"
"DisplayName" = "8:Confirm Installation"
"UseDynamicProperties" = "11:TRUE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdConfirmDlg.wid"
"Properties"
{
"BannerBitmap"
{
"Name" = "8:BannerBitmap"
"DisplayName" = "8:#1001"
"Description" = "8:#1101"
"Type" = "3:8"
"ContextData" = "8:Bitmap"
"Attributes" = "3:4"
"Setting" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
}
}
"{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_7A7EE4F003334B01BE835D840DF961DF"
{
"Sequence" = "3:300"
"DisplayName" = "8:Installation Folder"
"UseDynamicProperties" = "11:TRUE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdFolderDlg.wid"
"Properties"
{
"BannerBitmap"
{
"Name" = "8:BannerBitmap"
"DisplayName" = "8:#1001"
"Description" = "8:#1101"
"Type" = "3:8"
"ContextData" = "8:Bitmap"
"Attributes" = "3:4"
"Setting" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
"InstallAllUsersVisible"
{
"Name" = "8:InstallAllUsersVisible"
"DisplayName" = "8:#1059"
"Description" = "8:#1159"
"Type" = "3:5"
"ContextData" = "8:1;True=1;False=0"
"Attributes" = "3:0"
"Setting" = "3:0"
"Value" = "3:1"
"DefaultValue" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
}
}
}
}
"{DF760B10-853B-4699-99F2-AFF7185B4A62}:_FE23A7B7220447F981819CF713DF20E5"
{
"Name" = "8:#1902"
"Sequence" = "3:2"
"Attributes" = "3:3"
"Dialogs"
{
"{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_54098FCDE6914AEE8AA27CDB24E77DAF"
{
"Sequence" = "3:100"
"DisplayName" = "8:Finished"
"UseDynamicProperties" = "11:TRUE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdAdminFinishedDlg.wid"
"Properties"
{
"BannerBitmap"
{
"Name" = "8:BannerBitmap"
"DisplayName" = "8:#1001"
"Description" = "8:#1101"
"Type" = "3:8"
"ContextData" = "8:Bitmap"
"Attributes" = "3:4"
"Setting" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
}
}
}
}
}
"MergeModule"
{
}
"ProjectOutput"
{
"{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_68E75ECCCEB74C9DAEE029419E7ACA2B"
{
"SourcePath" = "8:..\\RPST\\obj\\Debug\\net6.0-windows\\apphost.exe"
"TargetName" = "8:"
"Tag" = "8:"
"Folder" = "8:_362735941ABB4269A087A0EAC1F3EB41"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:TRUE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
"ProjectOutputGroupRegister" = "3:1"
"OutputConfiguration" = "8:"
"OutputGroupCanonicalName" = "8:PublishItems"
"OutputProjectGuid" = "8:{46C2541E-6F65-461A-A479-F65D445C36EA}"
"ShowKeyOutput" = "11:TRUE"
"ExcludeFilters"
{
}
}
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 576 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 519 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 823 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 508 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -7,27 +7,27 @@ packages = ["rpst"]
[project]
name = "reddit-post-scraping-tool"
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."
version = "2.0.1.0"
description = "Retrieve Reddit posts that contain the specified keyword from a specified subreddit."
readme = "README.md"
requires-python = ">=3.8"
license = {file = "LICENSE"}
license = { file = "LICENSE" }
keywords = ["reddit-crawler", "reddit-scraping", "reddit", "reddit-api"]
authors = [{name = "Richard Mwewa", email = "rly0nheart@duck.com"}]
authors = [{ name = "Richard Mwewa", email = "rly0nheart@duck.com" }]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Programming Language :: Python :: 3",
"Programming Language :: Visual Basic",
"Intended Audience :: End Users/Desktop",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Natural Language :: English"
"Development Status :: 5 - Production/Stable",
"Programming Language :: Python :: 3",
"Programming Language :: Visual Basic",
"Intended Audience :: End Users/Desktop",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Natural Language :: English"
]
dependencies = [
"rich",
"glyphoji",
"requests",
"aiohttp",
"rich-argparse"
]
[project.urls]
@@ -36,4 +36,5 @@ documentation = "https://github.com/bellingcat/reddit-post-scraping-tool/wiki"
repository = "https://github.com/bellingcat/reddit-post-scraping-tool.git"
[project.scripts]
rpst = "rpst.main:run"
rpst = "rpst.scraper:run"
reddit_post_scraping_tool = "rpst.scraper:run"

View File

@@ -1 +1,42 @@
import os
__author__: str = "Richard Mwewa"
__about_author__: str = "https://about/me/rly0nheart"
__version__: str = "2.0.1.0"
__description__: str = f"""
# RPST (Reddit Post Scraping Tool) {__version__}
> Retrieve Reddit posts that contain the specified keyword from a specified subreddit.
"""
__epilog__: str = f"""
# by [{__author__}]({__about_author__})
```
MIT License
Copyright (c) 2023 {__author__}
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
"""
# Construct path to the program's directory
PROGRAM_DIRECTORY: str = os.path.expanduser(
os.path.join("~", "reddit_post_scraping_tool")
)

164
rpst/api.py Normal file
View File

@@ -0,0 +1,164 @@
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #
from typing import Union
import aiohttp
from .coreutils import log
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #
REDDIT_ENDPOINT: str = "https://www.reddit.com"
PYPI_PROJECT_ENDPOINT: str = "https://pypi.org/pypi/reddit-post-scraping-tool/json"
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #
async def get_data(session: aiohttp.ClientSession, endpoint: str) -> Union[dict, list]:
"""
Fetches JSON data from a given API endpoint.
:param session: aiohttp session to use for the request.
:param endpoint: The API endpoint to fetch data from.
:return: Returns JSON data as a dictionary or list. Returns an empty dict if fetching fails.
"""
try:
async with session.get(
endpoint,
) as response:
if response.status == 200:
return await response.json()
else:
error_message = await response.json()
log.error(f"An API error occurred: {error_message}")
return {}
except aiohttp.ClientConnectionError as error:
log.error(f"An HTTP error occurred: {error}")
return {}
except Exception as error:
log.critical(f"An unknown error occurred: {error}")
return {}
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #
async def get_updates(session: aiohttp.ClientSession):
"""
Gets and compares the current program version with the remote version.
Assumes version format: major.minor.patch.prefix
:param session: aiohttp session to use for the request.
"""
from . import __version__
# Make a GET request to PyPI to get the project's latest release.
response: dict = await get_data(endpoint=PYPI_PROJECT_ENDPOINT, session=session)
if response.get("info"):
release: dict = response.get("info")
remote_version: str = release.get("version")
# Splitting the version strings into components
remote_parts: list = remote_version.split(".")
local_parts: list = __version__.split(".")
update_message: str = ""
# Check for differences in version parts
if remote_parts[0] != local_parts[0]:
update_message = (
f"MAJOR update ({remote_version}) available."
f" It might introduce significant changes."
)
elif remote_parts[1] != local_parts[1]:
update_message = (
f"MINOR update ({remote_version}) available."
f" Includes small feature changes/improvements."
)
elif remote_parts[2] != local_parts[2]:
update_message = (
f"PATCH update ({remote_version}) available."
f" Generally for bug fixes and small tweaks."
)
elif (
len(remote_parts) > 3
and len(local_parts) > 3
and remote_parts[3] != local_parts[3]
):
update_message = (
f"BUILD update ({remote_version}) available."
f" Might be for specific builds or special versions."
)
if update_message:
log.info(update_message)
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #
async def get_posts(
subreddit: str,
listing: str,
timeframe: str,
limit: int,
session: aiohttp.ClientSession,
) -> list:
all_posts = await paginated_posts(
posts_endpoint=f"{REDDIT_ENDPOINT}/r/{subreddit}/{listing}.json?limit={limit}&t={timeframe}",
limit=limit,
session=session,
)
return all_posts[:limit]
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #
async def paginated_posts(
posts_endpoint: str, limit: int, session: aiohttp.ClientSession
) -> list:
"""
Paginates and retrieves posts until the specified limit is reached.
:param posts_endpoint: API endpoint for retrieving posts.
:param limit: Limit of the number of posts to retrieve.
:param session: aiohttp session to use for the request.
:return: A list of all posts.
"""
all_posts: list = []
last_post_id: str = ""
# Determine whether to use the 'after' parameter
use_after: bool = limit > 100
while len(all_posts) < limit:
# Make the API request with the 'after' parameter if it's provided and the limit is more than 100
if use_after and last_post_id:
endpoint_with_after: str = f"{posts_endpoint}&after={last_post_id}"
else:
endpoint_with_after: str = posts_endpoint
posts_data: dict = await get_data(endpoint=endpoint_with_after, session=session)
posts_children: list = posts_data.get("data", {}).get("children", [])
# If there are no more posts, break out of the loop
if not posts_children:
break
all_posts.extend(posts_children)
# We use the id of the last post in the list to paginate to the next posts
last_post_id: str = all_posts[-1].get("data").get("id")
return all_posts
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #

103
rpst/base.py Normal file
View File

@@ -0,0 +1,103 @@
# +++++++++++++++++++++++++++++++++++++++++++++++++ #
from dataclasses import dataclass
from typing import List
import aiohttp
from .api import get_posts, get_updates
from .coreutils import timestamp_to_utc
# +++++++++++++++++++++++++++++++++++++++++++++++++ #
@dataclass
class Post:
id: str
thumbnail: str
title: str
text: str
author: str
subreddit: str
subreddit_id: str
subreddit_type: str
upvotes: int
upvote_ratio: float
downvotes: int
gilded: int
is_nsfw: bool
is_shareable: bool
is_edited: bool
comments: int
hide_from_bots: bool
score: float
domain: str
permalink: str
is_locked: bool
is_archived: bool
created_at: str
raw_post: dict
# +++++++++++++++++++++++++++++++++++++++++++++++++ #
async def find_posts(
keyword: str,
subreddit: str,
listing: str,
timeframe: str,
limit: int,
) -> List[Post]:
async with aiohttp.ClientSession() as session:
found_posts_count: int = 0
found_posts_list: list = []
await get_updates(session=session)
raw_posts: list = await get_posts(
subreddit=subreddit,
listing=listing,
timeframe=timeframe,
limit=limit,
session=session,
)
for raw_post in raw_posts:
post_data: dict = raw_post.get("data")
if keyword.lower() in post_data.get(
"selftext"
) or keyword.lower() in post_data.get("title"):
found_posts_count += 1
post = Post(
id=post_data.get("id"),
thumbnail=post_data.get("thumbnail"),
title=post_data.get("title"),
text=post_data.get("selftext"),
author=post_data.get("author"),
subreddit=post_data.get("subreddit"),
subreddit_id=post_data.get("subreddit_id"),
subreddit_type=post_data.get("subreddit_type"),
upvotes=post_data.get("ups"),
upvote_ratio=post_data.get("upvote_ratio"),
downvotes=post_data.get("downs"),
gilded=post_data.get("gilded"),
is_nsfw=post_data.get("over_18"),
is_shareable=post_data.get("is_reddit_media_domain"),
is_edited=post_data.get("edited"),
comments=post_data.get("num_comments"),
hide_from_bots=post_data.get("is_robot_indexable"),
score=post_data.get("score"),
domain=post_data.get("domain"),
permalink=post_data.get("permalink"),
is_locked=post_data.get("locked"),
is_archived=post_data.get("archived"),
created_at=timestamp_to_utc(timestamp=post_data.get("created_utc")),
raw_post=post_data,
)
found_posts_list.append(post)
return found_posts_list
# +++++++++++++++++++++++++++++++++++++++++++++++++ #

170
rpst/coreutils.py Normal file
View File

@@ -0,0 +1,170 @@
# +++++++++++++++++++++++++++++++++++++++++++++++++ #
import argparse
import csv
import json
import logging
import os
from datetime import datetime
from rich.logging import RichHandler
from rich.markdown import Markdown
from rich_argparse import RichHelpFormatter
# +++++++++++++++++++++++++++++++++++++++++++++++++ #
def timestamp_to_utc(timestamp: int) -> str:
"""
Converts a Unix timestamp to a formatted datetime string.
:param timestamp: The Unix timestamp to be converted.
:return: A formatted datetime string in the format "dd MMMM yyyy, hh:mm:ssAM/PM".
"""
utc_from_timestamp: datetime = datetime.utcfromtimestamp(timestamp)
datetime_string: str = utc_from_timestamp.strftime("%d %B %Y, %I:%M:%S%p")
return datetime_string
# +++++++++++++++++++++++++++++++++++++++++++++++++ #
def pathfinder(directories: list[str]):
for directory in directories:
os.makedirs(directory, exist_ok=True)
# +++++++++++++++++++++++++++++++++++++++++++++++++ #
def save_posts(
filename: str,
save_to_dir: str,
posts: list,
save_json: bool = False,
save_csv: bool = False,
):
posts_data: list = [post.__dict__ for post in posts]
if save_json:
json_path = os.path.join(os.path.join(save_to_dir, "json"), f"{filename}.json")
with open(json_path, "w", encoding="utf-8") as json_file:
json.dump(posts_data, json_file, indent=4)
log.info(
f"{os.path.getsize(json_file.name)} bytes written to [link file://{json_file.name}]{json_file.name}"
)
if save_csv:
csv_path = os.path.join(os.path.join(save_to_dir, "csv"), f"{filename}.csv")
with open(csv_path, "w", newline="", encoding="utf-8") as csv_file:
writer = csv.writer(csv_file)
if posts:
writer.writerow(
posts_data[0].keys()
) # header from keys of the first item
for post in posts:
writer.writerow(post.__dict__.values())
log.info(
f"{os.path.getsize(csv_file.name)} bytes written to [link file://{csv_file.name}]{csv_file.name}"
)
# +++++++++++++++++++++++++++++++++++++++++++++++++ #
def create_parser():
"""
Creates and configures an argument parser for the command line arguments.
:return: A configured argparse.ArgumentParser object ready to parse the command line arguments.
"""
from . import __version__, __description__, __epilog__
parser = argparse.ArgumentParser(
description=Markdown(__description__, style="argparse.text"),
epilog=Markdown(__epilog__, style="argparse.text"),
formatter_class=RichHelpFormatter,
)
parser.add_argument(
"keyword",
help="keyword to search for, in posts",
)
parser.add_argument("subreddit", help="subreddit to scrape")
parser.add_argument(
"-l",
"--limit",
help="maximum number of posts to scrape (default: %(default)s)",
default=200,
type=int,
)
parser.add_argument(
"-ls",
"--listing",
default="top",
const="top",
nargs="?",
choices=["best", "controversial", "hot", "new", "rising", "top"],
help="listing of posts to scrape (default: %(default)s)",
)
parser.add_argument(
"-t",
"--timeframe",
default="all",
const="all",
nargs="?",
choices=["hour", "day", "week", "month", "year", "all"],
help="timeframe from which to scrape posts (default: %(default)s)",
)
parser.add_argument(
"-j",
"--json",
help="write found posts to a json file",
action="store_true",
)
parser.add_argument(
"-c",
"--csv",
help="write found posts to a csv file",
action="store_true",
)
parser.add_argument(
"-d",
"--debug",
help="(dev) run rpst in debug mode",
action="store_true",
)
parser.add_argument("-v", "--version", action="version", version=__version__)
return parser
# +++++++++++++++++++++++++++++++++++++++++++++++++ #
def set_loglevel(debug_mode: bool) -> logging.getLogger:
"""
Configure and return a logging object with the specified log level.
:param debug_mode: If True, the log level is set to "NOTSET". Otherwise, it is set to "INFO".
:return: A logging object configured with the specified log level.
"""
logging.basicConfig(
level="DEBUG" if debug_mode else "INFO",
format="%(message)s",
handlers=[
RichHandler(
markup=True, log_time_format="%I:%M:%S%p", show_level=debug_mode
)
],
)
return logging.getLogger("RPST (Reddit Post Scraping Tool)")
# +++++++++++++++++++++++++++++++++++++++++++++++++ #
args: argparse = create_parser().parse_args()
log: logging.getLogger = set_loglevel(debug_mode=args.debug)
# +++++++++++++++++++++++++++++++++++++++++++++++++ #

View File

@@ -1,33 +0,0 @@
from datetime import datetime
from .rpst import get_posts
from .utils import create_parser, set_loglevel, check_updates
def run():
"""
Main entry point for the program. It creates a parser, parses the command line arguments,
checks for updates, gets posts, and handles any exceptions that occur during the execution.
"""
# Create a parser and parse the command line arguments
parser = create_parser()
args = parser.parse_args()
log = set_loglevel(debug_mode=args.debug)
# Record the start time
start_time = datetime.now()
try:
# Check for updates
check_updates(version_tag="1.8.0.0")
# Get posts with the provided/parsed arguments
get_posts(args=args)
except KeyboardInterrupt:
log.warning("User interruption detected ([yellow]Ctrl+C[/]).")
except Exception as e:
log.error(f"An error occurred: [red]{e}[/]")
finally:
log.info(f"Finished in {datetime.now() - start_time} seconds.")

View File

@@ -1,131 +0,0 @@
import argparse
from datetime import datetime
import requests
from glyphoji import glyph
from rich import print
from rich.tree import Tree
from .utils import convert_timestamp_to_datetime, write_post_data
def create_post_branch(post: dict, keyword: str, tree: Tree, args: argparse) -> Tree:
"""
This function extracts relevant data from a Reddit post and adds it in a tree branch structure,
followed by the post's selftext.
:param post: A dictionary containing the data of a Reddit post.
:param keyword: The keyword that is used to find posts, in his case gets uses as the filename.
:param tree: Tree where the post branch will be added.
:param args: A namespace object from argparse.
:returns: The main tree with added post branches.
"""
# Define the data to extract from the post.
post_data = {
# "Author": post["data"]["author"],
f"{glyph.id_button} ID": post["data"]["id"],
f"{glyph.people_hugging} Subreddit": post["data"]["subreddit_name_prefixed"],
f"{glyph.face_with_peeking_eye} Visibility": post["data"]["subreddit_type"],
f"{glyph.framed_picture} Thumbnail": post["data"]["thumbnail"],
f"{glyph.white_question_mark} Gilded": post["data"]["gilded"],
f"{glyph.up_arrow} Upvotes": post["data"]["ups"],
f"{glyph.chart_increasing} Upvote ratio": post["data"]["upvote_ratio"],
f"{glyph.down_arrow} Downvotes": post["data"]["downs"],
f"{glyph.trophy} Awards": post["data"]["total_awards_received"],
f"{glyph.trophy} Top award": post["data"]["top_awarded_type"],
f"{glyph.no_one_under_eighteen} Is NSFW?": post["data"]["over_18"],
f"{glyph.left_arrow_curving_right} Is crosspostable?": post["data"][
"is_crosspostable"
],
f"{glyph.bar_chart} Score": post["data"]["score"],
f"{glyph.card_file_box} Category": post["data"]["category"],
f"{glyph.globe_with_meridians} Domain": post["data"]["domain"],
f"{glyph.calendar} Posted on": convert_timestamp_to_datetime(
post["data"]["created"]
),
f"{glyph.calendar} Approved at": post["data"]["approved_at_utc"],
f"{glyph.bust_in_silhouette} Approved by": post["data"]["approved_by"],
}
# Add the post's branch to the main tree.
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.
for post_key, post_value in post_data.items():
post_branch.add(f"{post_key}: {post_value}", style="dim")
# This ensures that the post's selftext is also added to the written json/csv file.
post_data[f"{glyph.clipboard} Text"] = post["data"]["selftext"]
write_post_data(
filename=keyword, post_data=post_data, tree_branch=post_branch, args=args
)
post_branch.add(post["data"]["selftext"], style="italic")
return tree
def get_posts(args: argparse):
"""
Scrapes a given subreddit for posts that contain a specified keyword.
The search is limited by the number of posts and timeframe specified.
:param args: Namespace object from argparse.
Expected Object Attributes
--------------------------
- keyword: The keyword to search for in the posts.
- subreddit: The subreddit to scrape.
- listing: The type of posts to scrape. This could be 'hot', 'new', etc.
- timeframe: The timeframe from which to scrape posts. This could be 'day', 'week', etc.
- limit: The maximum number of posts to scrape.
- json: If specified, all found posts will be written to a json file.
"""
keyword = args.keyword
subreddit = args.subreddit
listing = args.listing
timeframe = args.timeframe
limit = args.limit
# Create main result tree.
main_tree = Tree(
f"[bold]{glyph.calendar} {datetime.now()}[/]", guide_style="bold bright_blue"
)
# Start a new session
session = requests.session()
# Set the User-Agent to mimic a Safari browser on a Mac.
session.headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, "
"like Gecko) Version/14.1.1 Safari/605.1.15"
}
# Send a GET request to the specified subreddit and listing,
# limiting the response by the specified limit and timeframe.
response = session.get(
f"https://reddit.com/r/{subreddit}/{listing}"
f".json?limit={limit}&t={timeframe}"
).json()
# Initialize a counter for the number of posts found that contain the keyword.
found_posts = 0
# Loop through each post in the response
for post_index, post in enumerate(response["data"]["children"], start=1):
# If the keyword is found in the post's selftext or title, increment the counter and process the post.
if (
keyword.lower() in post["data"]["selftext"]
or keyword.lower() in post["data"]["title"]
):
# Create a branch for found post(s) and show post index and post author as the title
found_tree = main_tree.add(
f"{glyph.bust_in_silhouette} #{post_index} by [bold]@{post['data']['author']}[/]"
)
found_posts += 1
create_post_branch(post=post, keyword=keyword, tree=found_tree, args=args)
# Log the number of posts in which the keyword was found
main_tree.add(
f"{glyph.check_mark_button} Keyword ('{keyword}') was found in "
f"{found_posts}/{len(response['data']['children'])} {listing} posts from r/{subreddit}."
)
print(main_tree)

94
rpst/scraper.py Normal file
View File

@@ -0,0 +1,94 @@
# +++++++++++++++++++++++++++++++++++++++++++++++++ #
import asyncio
import os
from datetime import datetime
from rich.pretty import pprint
from . import __version__, PROGRAM_DIRECTORY
from .base import find_posts
from .coreutils import args, log, save_posts, pathfinder
# +++++++++++++++++++++++++++++++++++++++++++++++++ #
def run():
"""Main entry point for rpst or rpst."""
# ------------------------------------- #
keyword: str = args.keyword
subreddit: str = args.subreddit
listing: str = args.listing
limit: int = args.limit
# ------------------------------------- #
start_time = datetime.now()
# ------------------------------------- #
print(
"""
┳┓┏┓┏┓┏┳┓
┣┫┃┃┗┓ ┃
┛┗┣┛┗┛ ┻ """
)
# ------------------------------------- #
try:
log.info(
f"[bold]RPST[/] {__version__} started at {start_time.strftime('%a %b %d %Y, %I:%M:%S%p')}..."
)
found_posts = asyncio.run(
find_posts(
keyword=keyword,
subreddit=subreddit,
listing=listing,
timeframe=args.timeframe,
limit=limit,
),
)
if found_posts:
pprint(
found_posts,
expand_all=True,
)
log.info(
f"'{subreddit}': Found {len(found_posts)}/{limit} {listing} posts containing the keyword ('{keyword}')"
)
if args.json or args.csv:
target_dir: str = os.path.join(PROGRAM_DIRECTORY, subreddit)
pathfinder(
directories=[
os.path.join(target_dir, "csv"),
os.path.join(target_dir, "json"),
]
)
save_posts(
filename=keyword,
save_to_dir=target_dir,
posts=found_posts,
save_json=args.json,
save_csv=args.csv,
)
else:
log.info(
f"'r/{subreddit}': No {listing} posts found that contain the keyword ('{keyword}')"
)
except KeyboardInterrupt:
log.warning("User interruption detected ([yellow]Ctrl+C[/])")
except Exception as error:
log.error(f"An error occurred: [red]{error}[/]")
finally:
log.info(f"Finished in {datetime.now() - start_time} seconds")
# ------------------------------------- #
# +++++++++++++++++++++++++++++++++++++++++++++++++ #

View File

@@ -1,183 +0,0 @@
import os
import csv
import json
import logging
import argparse
from datetime import datetime
import requests
from glyphoji import glyph
from rich import print
from rich.tree import Tree
from rich.markdown import Markdown
from rich.logging import RichHandler
def convert_timestamp_to_datetime(timestamp: int) -> str:
"""
Converts a Unix timestamp to a formatted datetime string.
:param timestamp: The Unix timestamp to be converted.
:return: A formatted datetime string in the format "dd MMMM yyyy, hh:mm:ssAM/PM".
"""
utc_from_timestamp = datetime.utcfromtimestamp(timestamp)
datetime_object = utc_from_timestamp.strftime("%d %B %Y, %I:%M:%S%p")
return datetime_object
def create_parser():
"""
Creates and configures an argument parser for the command line arguments.
:return: A configured argparse.ArgumentParser object ready to parse the command line arguments.
"""
parser = argparse.ArgumentParser(
description="RPST (Reddit Post Scraping Tool) —by Richard Mwewa | https://about.me/rly0nheart",
epilog="Given a subreddit name and a keyword, "
"RPST returns all top (by default) posts that contain the specified keyword.",
)
parser.add_argument(
"-k", "--keyword", help="The keyword to search for in the posts.", required=True
)
parser.add_argument(
"-s", "--subreddit", help="The subreddit to scrape.", required=True
)
parser.add_argument(
"-c",
"--limit",
help="The maximum number of posts to scrape (1-100). (default: %(default)s)",
default=10,
type=int,
choices=range(
1, 101
), # This enforces that the limit must be between 1 and 100 inclusive.
)
parser.add_argument(
"-l",
"--listing",
default="top",
const="top",
nargs="?",
choices=["controversial", "hot", "best", "new", "rising"],
help="The type of posts to scrape (default: %(default)s)",
)
parser.add_argument(
"-t",
"--timeframe",
default="all",
const="all",
nargs="?",
choices=["hour", "day", "week", "month", "year", "all"],
help="The timeframe from which to scrape posts (default: %(default)s)",
)
parser.add_argument(
"--json",
help="Write all found posts to a json file.",
action="store_true",
)
parser.add_argument(
"--csv",
help="Write all found posts to a csv file.",
action="store_true",
)
parser.add_argument(
"-d",
"--debug",
help="run rpst in debug mode",
action="store_true",
)
return parser
def check_updates(version_tag: str):
"""
This function checks if there's a new release of a project on GitHub. If there is, it logs an
information message and prints the release notes.
:param version_tag: A string representing the current version of the project.
"""
# Make a GET request to the GitHub API to get the latest release of the project.
response = requests.get(
"https://api.github.com/repos/bellingcat/reddit-post-scraping-tool/releases/latest"
).json()
# Check if the latest release's tag matches the current version tag.
if response["tag_name"] != version_tag:
# If not, convert the release notes from Markdown to HTML.
raw_release_notes = response["body"]
# Log an info message about the new release.
print(
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."
)
# Print the release notes.
print(Markdown(raw_release_notes))
def set_loglevel(debug_mode: bool) -> logging.getLogger:
"""
Configure and return a logging object with the specified log level.
:param debug_mode: If True, the log level is set to "NOTSET". Otherwise, it is set to "INFO".
:return: A logging object configured with the specified log level.
"""
logging.basicConfig(
level="NOTSET" if debug_mode else "INFO",
format="%(message)s",
handlers=[
RichHandler(markup=True, log_time_format="[%I:%M:%S %p]", show_level=False)
],
)
return logging.getLogger("RPST")
def write_post_data(post_data: dict, filename: str, args, tree_branch: Tree):
"""
Writes post data to a specified JSON or CSV file based on the args provided, and updates
the provided tree with the status.
:param post_data: A dictionary containing post data.
:param filename: The name of the file to which post data will be written.
:param args: A namespace object from argparse containing the output format options (args.json or args.csv).
:param tree_branch: A rich Tree object to which status information will be added.
"""
home_directory = os.path.expanduser("~")
if args.json:
json_file_path = os.path.join(home_directory, f"{filename}.json")
with open(json_file_path, "a", encoding="utf-8") as file:
file.write(json.dumps(post_data, ensure_ascii=False))
file.write("\n") # Separate posts with newline
tree_branch.add(
f"{glyph.page_facing_up} JSON data successfully written/appended to file: "
f"[italic][link file://{json_file_path}]{json_file_path}[/]"
)
else:
tree_branch.add(
f"{glyph.cross_mark_button} JSON data writing operation was skipped. No changes made."
)
if args.csv:
csv_file_path = os.path.join(home_directory, f"{filename}.csv")
with open(csv_file_path, "a", newline="", encoding="utf-8") as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=post_data.keys())
# Write headers if file is empty
if csvfile.tell() == 0:
writer.writeheader()
writer.writerow(post_data)
tree_branch.add(
f"{glyph.page_facing_up} CSV data successfully written/appended to file: "
f"[italic][link file://{csv_file_path}]{csv_file_path}[/]"
)
else:
tree_branch.add(
f"{glyph.cross_mark_button} CSV data writing operation was skipped. No changes made."
)